Include DNS/ASN-verified crawlers in the path breakdown
The path breakdown was populated only inside the IP-range branch, so it silently covered one of the two verification methods. Vendors confirmed by PTR or ASN - YouBot, Amazonbot, Meta - were counted in their own table but contributed nothing to the only output that shows what crawlers actually fetch. On the sample instance that hid roughly 40% of the verified requests from the path list. Collect paths per address during the log pass and merge them once the address is confirmed, whichever method confirms it. Private-source hits are excluded, since those addresses are never judged either way. Move the section to the end of the report and retitle it: it now spans both tables above, so placing it under the IP-range table implied a narrower scope than it has. Assisted-by: Claude:opus-5
This commit is contained in:
parent
2e9f48e4d2
commit
3b80ddeba0
1 changed files with 23 additions and 6 deletions
|
|
@ -258,6 +258,10 @@ ver_ips = {} # bot -> set of verified source IPs
|
|||
# rDNS-verified vendors: {bot: {ip: hits}}, resolved after the log pass
|
||||
rdns_hits = {b: Counter() for b in BOT_RDNS}
|
||||
rdns_proxied = Counter()
|
||||
# {bot: {ip: Counter(path)}} - kept so that once an address is confirmed
|
||||
# by DNS/ASN its paths can join the verified-path breakdown, which
|
||||
# otherwise only ever showed IP-range-verified vendors.
|
||||
rdns_paths = {b: {} for b in BOT_RDNS}
|
||||
for path in sorted(glob.glob(LOG_GLOB)):
|
||||
opener = gzip.open if path.endswith(".gz") else open
|
||||
with opener(path, "rt", errors="replace") as f:
|
||||
|
|
@ -313,6 +317,9 @@ for path in sorted(glob.glob(LOG_GLOB)):
|
|||
rdns_proxied[rb] += 1
|
||||
else:
|
||||
rdns_hits[rb][parts[0]] += 1
|
||||
if len(parts) > 6 and not a2.is_private:
|
||||
rdns_paths[rb].setdefault(
|
||||
parts[0], Counter())[parts[6][:60]] += 1
|
||||
break
|
||||
|
||||
total = sum(v[0] for v in per_day.values())
|
||||
|
|
@ -345,19 +352,24 @@ if WEEKLY and RDNS_ENABLE:
|
|||
continue
|
||||
budget -= 1
|
||||
ok, _host, why = fcrdns(ip, BOT_RDNS[bot])
|
||||
confirmed = False
|
||||
if ok:
|
||||
rdns_ok[bot] += hits
|
||||
rdns_ok_ips.setdefault(bot, set()).add(ip)
|
||||
confirmed = True
|
||||
elif why == "no-ptr":
|
||||
# Fall back to ASN, but only for vendors whose network is
|
||||
# single-tenant (see BOT_ASN). Otherwise leave it unknown.
|
||||
if ASN_ENABLE and bot in BOT_ASN and asn_of(ip) in BOT_ASN[bot]:
|
||||
rdns_asn[bot] += hits
|
||||
rdns_ok_ips.setdefault(bot, set()).add(ip)
|
||||
confirmed = True
|
||||
else:
|
||||
rdns_noptr[bot] += hits
|
||||
else:
|
||||
rdns_mismatch[bot] += hits
|
||||
if confirmed:
|
||||
ver_paths.update(rdns_paths.get(bot, {}).get(ip, ()))
|
||||
socket.setdefaulttimeout(None)
|
||||
|
||||
if not WEEKLY:
|
||||
|
|
@ -409,12 +421,6 @@ else:
|
|||
lines.append(f" {claimed} requests claimed an AI-bot identity; {tv} verified ({pct:.1f}%).")
|
||||
lines.append(f" {ts} failed IP verification (spoofed). {tp} arrived via Cloudflare")
|
||||
lines.append(" and cannot be verified by IP - not counted either way.")
|
||||
if ver_paths:
|
||||
lines.append("")
|
||||
lines.append(" Top paths fetched by verified crawlers:")
|
||||
for p, c in ver_paths.most_common(8):
|
||||
lines.append(f" {c:>6} {p}")
|
||||
|
||||
# --- vendors verified by reverse DNS ---------------------------------
|
||||
if RDNS_ENABLE and (rdns_ok or rdns_mismatch or rdns_noptr or rdns_asn
|
||||
or rdns_proxied or rdns_private):
|
||||
|
|
@ -448,6 +454,17 @@ else:
|
|||
if sum(rdns_private.values()):
|
||||
lines.append(" priv logged source was RFC1918: a proxy or Docker")
|
||||
lines.append(" bridge masked the client. Unjudgeable. See README.")
|
||||
|
||||
# --- what the verified crawlers actually fetched ---------------------
|
||||
# Last, because it spans both tables above: an address only counts here
|
||||
# once it has been confirmed, whether by IP range, PTR or ASN.
|
||||
if ver_paths:
|
||||
lines.append("")
|
||||
lines.append("=" * 62)
|
||||
lines.append("TOP PATHS FETCHED BY VERIFIED CRAWLERS (all methods)")
|
||||
lines.append("=" * 62)
|
||||
for p, c in ver_paths.most_common(12):
|
||||
lines.append(f" {c:>6} {p}")
|
||||
body = "\n".join(lines) + "\n"
|
||||
subject = f"{SITE} weekly crawler report: {total} requests, {len(all_ips)} IPs"
|
||||
if DRY:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue