-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbatch-check.sh
More file actions
106 lines (95 loc) · 3.43 KB
/
Copy pathbatch-check.sh
File metadata and controls
106 lines (95 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env bash
# batch-check.sh — 批量质检代理 / IP 列表,输出 CSV(ipyou.net)
#
# 站点不提供批量接口,本脚本就是「循环调用单个接口」的现成实现:
# 自动去重、限速(默认每个 1 秒)、失败重试,并把结果拼成 CSV。
#
# 用法:
# ./batch-check.sh ips.txt 输出 CSV 到 stdout
# ./batch-check.sh ips.txt > out.csv 存文件(Excel 可直接打开)
# cat ips.txt | ./batch-check.sh 从管道读
# ./batch-check.sh -t ips.txt 人眼友好的表格(非 CSV)
# IPYOU_SLEEP=2 ./batch-check.sh ips.txt 放慢一点
#
# 输入格式: 每行一个 IP,支持 host:port / user:pass@host:port、# 注释、空行
# 依赖: curl + jq
set -euo pipefail
BASE="${IPYOU_BASE:-https://ipyou.net}"
TIMEOUT="${IPYOU_TIMEOUT:-15}"
SLEEP="${IPYOU_SLEEP:-1}" # 每个 IP 之间的间隔,别把公共服务打爆
table=0
usage() { sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'; exit 0; }
while [ $# -gt 0 ]; do
case "$1" in
-t|--table) table=1; shift ;;
-h|--help) usage ;;
*) break ;;
esac
done
command -v jq >/dev/null 2>&1 || { echo "需要 jq: https://jqlang.github.io/jq/" >&2; exit 3; }
src="${1:--}"
ips=$(sed 's/#.*//' "$src" \
| grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' \
| awk '!seen[$0]++')
[ -n "$ips" ] || { echo "没有找到可检测的 IP" >&2; exit 1; }
total=$(printf '%s\n' "$ips" | wc -l | tr -d ' ')
echo "共 $total 个 IP,逐个查询中(间隔 ${SLEEP}s)…" >&2
if [ "$table" = "0" ]; then
echo "ip,country,city,isp,asn,type,score,level,blocklisted,tiktok,ecom,social,ai"
fi
# 取单个 IP 的 JSON;429 时退避重试
fetch() {
local ip="$1" try out code
for try in 1 2 3; do
out=$(curl -s -w '\n%{http_code}' --max-time "$TIMEOUT" \
-H "Accept: application/json" "$BASE/$ip" || true)
code=$(printf '%s' "$out" | tail -1)
if [ "$code" = "200" ]; then
printf '%s' "$out" | sed '$d'
return 0
fi
[ "$code" = "429" ] || return 1
sleep $((try * 5)) # 触发限流:退避后重试
done
return 1
}
n=0
while IFS= read -r ip; do
[ -z "$ip" ] && continue
n=$((n + 1))
[ "$n" -gt 1 ] && sleep "$SLEEP"
if ! json=$(fetch "$ip"); then
echo " ! $ip 查询失败,跳过" >&2
continue
fi
if [ "$table" = "1" ]; then
echo "$json" | jq -r '
[ .ip,
(.usage_inferred.label // "-"),
((.ip_score.score // "") | tostring),
(.ip_score.level // "-"),
(if .blocklisted then "BLOCKED" else "-" end),
(.geo_consensus.country_name // .geo.country // "-"),
(.geo.isp // .geo_consensus.isp // "-") ] | @tsv' \
| awk -F'\t' '{printf "%-16s %-10s %4s %-8s %-8s %-22s %s\n", $1,$2,$3,$4,$5,$6,$7}'
else
echo "$json" | jq -r '
(.scenarios // []) as $s |
[ .ip,
(.geo_consensus.country_name // .geo.country // ""),
(.geo_consensus.city // .geo.city // ""),
(.geo.isp // .geo_consensus.isp // ""),
(if .asn.number then "AS\(.asn.number)" else "" end),
(.usage_inferred.label // ""),
(.ip_score.score // ""),
(.ip_score.level // ""),
(.blocklisted // false),
($s | map(select(.name=="TikTok")) | (.[0].stars // "")),
($s | map(select(.name=="跨境电商")) | (.[0].stars // "")),
($s | map(select(.name=="社媒运营")) | (.[0].stars // "")),
($s | map(select(.name=="AI 应用")) | (.[0].stars // ""))
] | @csv'
fi
done <<EOF
$ips
EOF