API¶
netspy.AirSpider
¶
Bases: BaseParser
netspy.Spider
¶
Bases: BaseParser
netspy.TaskSpider
¶
Bases: Spider
task_requests(task)
¶
把一个任务(dict)变成一个或多个 Request。必须实现。
fetch_tasks(limit)
¶
拉一批任务。默认从 Redis list 取;覆写以从 MySQL / Mongo 查。
add_tasks(*tasks)
¶
运行中追加任务(比如在 parse 里发现了新的待抓项)。
push_tasks(*tasks, task_key=None)
classmethod
¶
生产者用:把任务塞进 Redis 任务源。
task_key 默认是类名,不是消费者那边的 redis_key——这里是
classmethod,拿不到任何实例的 redis_key。消费者如果自定义了
redis_key 却没给它显式传 task_key,它的任务源默认会跟着
redis_key 走;这时必须在这里也显式传同一个 task_key
(通常就传那个 redis_key 的值),否则推的任务和消费者读的是两个
不同的 Redis key——推了但没人读,消费者看到空队列直接判定「任务耗尽」
退出,不会有任何报错。
start()
¶
stop()
¶
netspy.BatchSpider
¶
Bases: BaseParser
task_requests(task)
¶
把一个任务(任务表的一行 dict)变成一个或多个 Request。必须实现。
框架会自动给每个 Request 补上 cb_kwargs['task'],回调里可直接拿到。
update_task(task_id, *, ok=True)
¶
回写任务状态:ok=True → 已完成;ok=False → 失败(不再重试)。
标「已完成」会等这次请求产出的数据真正落库之后才写任务表。
照文档在回调里 yield 完 item 紧接着调用它 —— 那一刻数据还只在内存缓冲里,
立刻写 DONE 的话,节点一死数据就没了,而防丢机制只回收「处理中」,
标了 DONE 的任务永远不会被重跑。真库实测:5 个任务全标 DONE,落库 0 行。
三条例外走立即写入:没产出 item 的请求(否则永远等不到落库)、
ok=False(标失败不取决于数据)、以及不在请求上下文里调用(比如 master)。
failed_request(request, response)
¶
重试耗尽后:把对应任务标为失败。覆写时记得 super()。
start()
¶
worker:消费 master 推来的任务。
start_monitor(*, once=False)
¶
master:管理批次生命周期。once=True 跑完一个批次即返回。
stop()
¶
netspy.core.batch_store.BatchStore
¶
Bases: ABC
ensure_schema()
abstractmethod
¶
建批次记录表(幂等)。任务表由用户自行创建。
latest_batch()
abstractmethod
¶
最近一个批次(不管是否完成),没有则 None。
batch_age_seconds(batch_id)
abstractmethod
¶
批次创建至今的秒数。
reset_all_tasks()
abstractmethod
¶
所有任务状态 → 待处理(开新批次时调用)。
reset_lost_tasks(stale_seconds)
abstractmethod
¶
「处理中」且超过 stale_seconds 没更新的任务 → 待处理;返回重置数量。
claim_tasks(limit)
abstractmethod
¶
认领至多 limit 个待处理任务(状态置为处理中),返回整行。
mark_task(task_id, state)
abstractmethod
¶
回写单个任务状态(worker 解析完成 / 失败后调用)。
close()
¶
释放连接。
netspy.core.batch_monitor.BatchMonitor
¶
netspy.BaseParser
¶
Bases: LoggerMixin
start_requests()
¶
产出种子请求。
parse(request, response)
¶
默认回调。未给 Request 指定 callback 时调用。
download_midware(request)
¶
下载前的最后一次修改机会。返回 Request 以替换,返回 None 用原请求。
validate(request, response)
¶
校验响应。返回 False 丢弃;抛 ValidationError 触发重试;抛 NotRetryError 丢弃。
failed_request(request, response)
¶
重试耗尽后的兜底。可再 yield Request / 数据。
exception_request(request, response, exception)
¶
下载 / 解析抛异常且仍会重试时调用(观测用,通常不 yield)。
user_pool()
¶
返回一个账号池,返回 None 表示不用。调度器会自动挂到下载链上。
check_login(response)
¶
用了账号池时判断响应是否处于登录态。返回 False -> 拉黑当前账号并换号重试。
start_callback()
¶
爬虫启动时调用一次。
end_callback()
¶
爬虫正常结束时调用一次。
netspy.Response
¶
from_httpx(resp, request=None, content=None)
classmethod
¶
content 由流式下载的调用方传入 —— 流式响应上取 resp.content 会抛
ResponseNotRead,而且那样也绕开了大小上限。
from_curl_cffi(resp, request=None, content=None)
classmethod
¶
由 :mod:curl_cffi 的响应构造(与 :meth:from_httpx 平行)。
与 httpx 的差异:elapsed 已经是秒(float)而非 timedelta,
编码属性叫 charset_encoding,history 里是完整响应对象。
netspy.pipelines.base.BasePipeline
¶
netspy.pipelines.mysql.MysqlPipeline
¶
Bases: SqlPipeline
netspy.db.mysqldb.MysqlDB
¶
from_url(url)
classmethod
¶
mysql://user:pass@host:3306/dbname
transaction()
¶
在同一条连接上跑多条语句,出错回滚。
普通的 query / execute 各自从池里借一条连接、用完就还,而且池是
autocommit=True 的 —— 所以「先 SELECT ... FOR UPDATE 再 UPDATE」
这种写法在它们身上根本锁不住:两条语句在两条连接、两个事务里,
行锁在第一条语句结束时就放掉了。
需要「读到什么就锁住什么」的地方(比如多 worker 抢任务)必须用这个。
insert(sql, args=None)
¶
执行一条 INSERT,返回自增主键(cursor.lastrowid)。
netspy.User
dataclass
¶
netspy.network.user_pool.base.UserPool
¶
netspy.GuestUserPool
¶
Bases: LocalUserPool
netspy.network.middleware.DownloaderMiddleware
¶
Bases: LoggerMixin
基类,子类按需覆写。子类里可以直接 self.logger.info(...)。
netspy.network.proxy_pool.base.ProxyPool
¶
Bases: ABC
get_proxy()
abstractmethod
¶
返回一个可用代理(形如 http://host:port),无则返回 None。
report_bad(proxy)
¶
标记某代理不可用 —— 确定是代理自己的错(连不上、CONNECT 被拒)。
report_suspect(proxy)
¶
一次说不清是谁的错的失败(读超时、连接重置、响应畸形)。
默认不作为 —— 自定义代理池不实现它,就等于「目标站的锅不算代理头上」,
这是安全的方向。内置的 ApiProxyPool 会连续攒够
PROXY_SUSPECT_BAN_AFTER 次才拉黑。
report_good(proxy)
¶
这个代理刚成功完成了一次请求 —— 用来把连续失败计数清零。
⚠️ 它在每个成功请求上都会被调用,实现必须便宜。
close()
¶
释放资源。