怎么核对你的代理服务商用量表是否诚实
一个你没法验证的仪表盘数字不是账单,只是一个说法。这里讲怎么量自己这边的流量再拿去对,不管你买的是谁家的。
如果你曾经眼看着 5GB 余额在一下午的轻量抓取里蒸发掉,那你多半动过这个念头:这玩意儿到底算没算对?
通常你答不上来。多数服务商只给你一个数字,每隔几分钟刷新一次,背后什么都没有。你被要求相信一个自己无从还原的总数。这不是在指控哪一家公司。这是一种糟糕的安排,而这个市场的低价段几乎全都建立在这种安排上。
好消息是,你自己这一侧是可以量的。方法如下。
先量你自己这边
你要的是客户端通过代理实际收到的字节数。要的是走线上的字节,不是页面大小,也不是 Content-Length 头。
在 Python 里,把响应包一层:
import requests
TOTAL = 0
def get(url, **kw):
global TOTAL
r = requests.get(url, **kw)
# 响应正文加上头部块,这正是代理计量的口径。
header_bytes = sum(len(k) + len(v) + 4 for k, v in r.headers.items())
TOTAL += len(r.content) + header_bytes
return r
# ... 跑你的任务 ...
print(f"{TOTAL / 1_000_000_000:.3f} GB")
在 Node 里,如果你用 undici 或者 fetch,要在数据块到达时就累加,别等缓冲完再算,这样中途放弃的响应也能被计进去。
这里有两件事很多人会搞错:
- 压缩。 如果服务端发的是 gzip,而你的客户端透明地解压了,那么
len(r.content)是解压后的大小,可能是应计费数字的三到四倍。测量期间把Accept-Encoding设成identity,或者直接在 socket 层面数。 - 重试。 你的 HTTP 库可能在悄悄重试失败的请求。每一次尝试都是流量。测试时把重试关掉。
然后拿去对
跑一个足够大的任务,一个 GB 左右,再把你的总数和服务商的总数对一下。
差个一两个百分点是正常的,也没什么好说的。那是 TLS 开销、连接建立,以及你量的位置和他们量的位置不同带来的差异。
差二十个百分点,就该谈一谈了。
值得问的几个问题
不管你买的是谁家的,下面这四个问题能把「用量表」和「一个数字」区分开:
- 我能看到逐条请求的用量,还是只有一个总数? 总数没法核。一行行的记录可以。
- 哪些失败的请求要计费? 超时或连接重置没有从网站带回任何东西。429 或封锁页带回了东西,多数用量表会算它。问清楚这条线划在哪里。
- 计费算的是请求字节,还是只算响应字节? 两种口径都站得住。不说是哪一种就站不住。
- 我能导出日志吗? 如果答案是不能,那你永远没有任何办法去审计任何东西。
如果一家服务商没法用一句话分别回答这四个问题,这本身就说明了一些事。
我们是怎么做的
我们把每条请求单独记录,带 ID、主机、国家、状态码和字节数,你可以把整份导成 CSV。连接失败(超时、连接重置和我们自己网关的错误)计零,并且照样留在日志里标为免费,所以你既看得见它发生过,也看得见它没花钱。网站发回来的 429、5xx 或封锁页算流量,和任何响应一样。
还有一个长期有效的承诺:如果你数的和我们数的相差超出实话实说页上写明的容差,把两个数字都发给我们,我们先按你的重算这次会话的账,然后再去查差异出在哪。你不需要先证明我们错了。
这些都正式写在实话实说页上。
拿上面那个测试来测我们。它就是为这个准备的。