API 参考¶
本节由 mkdocstrings 从源码 docstring 自动生成。
所有公开 API 均通过 web_crawler 顶层包导出,懒加载,import web_crawler 不会
强制加载 playwright / curl_cffi 等可选依赖。
顶层导出¶
web_crawler
¶
web_crawler — 对齐 Scrapling 的隐身抓取库。
公开接口对齐 Scrapling 的高层 API:
- :class:
Selector/ :class:Adaptors— 自适应 lxml 选择器,支持元素指纹 与结构相似度重定位。 - :class:
Response— 带选择器助手的归一化抓取结果。 - :class:
Fetcher— 基于curl_cffiTLS 指纹的隐身 HTTP(httpx 兜底)。 - :class:
AsyncFetcher— 纯异步 fetcher(同样的隐身能力,纯异步 API)。 - :class:
DynamicFetcher— Playwright 渲染抓取。 - :class:
StealthyFetcher— 反反爬 / 感知 Cloudflare 的 Playwright fetcher。 - :class:
ProxyPool— 轮询 / 随机代理轮换,带健康跟踪。 - :class:
SessionPool— curl_cffi 会话池,指纹随会话轮换(round_robin / random),空闲回收与失败淘汰。 - :class:
Spider/ :class:Request— 回调驱动的 spider 框架,支持 暂停/恢复、:class:CacheMiddleware磁盘缓存(TTL / 离线回放)、 :class:AutoThrottle自适应限速、robotsCrawl-delay遵守与 stats JSON/JSONL 导出。 - :class:
WebCrawlerError— 统一异常体系根(子类兼容ValueError/RuntimeError),可用except WebCrawlerError一次捕获库自身的错误。
所有公开符号均为惰性导入:import web_crawler 不会引入 playwright
或 curl_cffi。重型子模块仅在对应类首次访问时加载(Scrapling 采用同样
的模式)。
快速上手¶
from web_crawler import Fetcher, Selector fetcher = Fetcher(impersonate="chrome131") resp = fetcher.get("https://example.com") for link in resp.css("a"): ... print(link.attr("href"))
AIExtractor
¶
基于 LLM 的选择器生成,带校验与自愈。
Parameters¶
provider:
任意满足 :class:~web_crawler.ai.llm.LLMProvider 的对象。缺省时
创建 DeepSeek 供应商(模型 DeepSeek-V4.1-Flash)。
model:
便捷参数:透传给默认供应商的模型名。
max_html_chars:
发送给模型的 HTML 样本长度上限(控制 prompt 体积)。
max_heal_rounds:
针对空字段最多额外尝试的修正轮数。
源代码位于: src/web_crawler/ai/extractor.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | |
extract
¶
extract(
source: Response | Selector,
schema: dict[str, str],
*,
self_heal: bool = True,
) -> ExtractionResult
抽取 schema 字段,并对选择器做校验与自愈。
返回 :class:ExtractionResult,包含抽取的 data、最终使用的
selectors,以及仍未能解析的 missing 字段。
源代码位于: src/web_crawler/ai/extractor.py
suggest_selectors
¶
suggest_selectors(
source: Response | Selector,
schema: dict[str, str],
*,
failing: dict[str, str] | None = None,
) -> dict[str, str]
向模型请求 {field: css} 映射(不做校验)。
源代码位于: src/web_crawler/ai/extractor.py
AIProviderError
¶
Bases: WebCrawlerError, RuntimeError
LLM / VLM 供应商调用失败(缺 API key、接口报错、空响应)。
典型触发场景:ai/llm.py 的 provider 未配置 API key、
parser/visual.py 的 VLM 调用失败 / 空响应(均已接入)。
兼容基类 :class:RuntimeError:存量 AI 层失败统一以
RuntimeError 表达,切换后 except RuntimeError 断言原样通过。
源代码位于: src/web_crawler/exceptions.py
AIScrapeAgent
¶
AI 辅助爬虫,自带速率控制。
Parameters¶
fetcher:
任意带 get(url) 或 fetch(url) 方法且返回 :class:Response
的对象。缺省时延迟创建 fetcher(render=True 用
:class:DynamicFetcher,否则 :class:Fetcher)。
render:
对 JS 密集页面使用 Playwright 后端的 :class:DynamicFetcher。
provider:
用于抽取的 LLM 供应商(默认 DeepSeek / DeepSeek-V4.1-Flash)。
min_delay:
相邻请求之间的最小间隔秒数(限速)。
respect_robots:
跳过 robots.txt 禁止的 URL。
max_retries:
遇 429/503 时的指数退避重试次数。
user_agent:
robots.txt 检查使用的 User-Agent 字符串。
detect_blocks:
检测反爬/验证码墙并移交人工,而非尝试绕过(受 BrowserAct 启发
的负责任变体)。
on_block:
检测到拦截时以 :class:ScrapeResult 为参数调用的可选回调
(例如通知运维或打开手动浏览器)。
源代码位于: src/web_crawler/ai/agent.py
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | |
close
¶
fetch
¶
礼貌地抓取 url:robots 检查、限速、429/503 退避。
源代码位于: src/web_crawler/ai/agent.py
scrape
¶
抓取 url 并用 AI 抽取器抽取 schema 字段。
若 detect_blocks 开启且页面看起来是反爬/验证码墙,则跳过抽取,
返回 needs_human=True 的 :class:ScrapeResult(并调用
on_block)。
源代码位于: src/web_crawler/ai/agent.py
AdaptiveStorage
¶
线程安全的自适应元素指纹 SQLite 存储。
源代码位于: src/web_crawler/parser/storage.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
Adaptors
¶
面向单个域名的自适应存储门面。
源代码位于: src/web_crawler/parser/selector.py
AsyncFetcher
¶
Bases: _FetcherCore
纯异步隐身 HTTP fetcher(对齐 Scrapling 的 AsyncFetcher)。
与 :class:Fetcher 共享全部配置、后端选择与重试逻辑,但只暴露
异步 API。没有同步 get/post 方法,意图明确且绝不创建同步会话。
异步应用中使用它,可避免同步调用意外阻塞事件循环。构造参数与
:class:Fetcher 完全一致——包括可选的 session_pool(异步借还
走池的 acquire_async / release_async)。
源代码位于: src/web_crawler/fetchers/fetcher.py
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 | |
aclose
async
¶
异步关闭异步会话(同步会话从不创建)。
源代码位于: src/web_crawler/fetchers/fetcher.py
request
async
¶
AutoThrottle
¶
按域自适应限速器:EMA 延迟反馈 + 失败惩罚 + 目标并发换算。
供 :class:~web_crawler.spider.Spider 的 autothrottle 构造参数
注入;也可独立使用(任何能按域反馈 (elapsed, success) 的调度器
都能驱动它)。
Parameters¶
alpha:
EMA 平滑系数, (0, 1];越大越贴近最新样本、越小越平滑。
默认 0.3。
target_concurrency:
目标并发(对齐 Scrapy AUTOTHROTTLE_TARGET_CONCURRENCY):
希望同域同时保持的请求数。target_delay = EMA / 该值。
默认 1.0。
min_delay:
延迟下限(秒)。默认 0.0。
max_delay:
延迟上限(秒),同时兜底惩罚放大后的极端值。默认 60.0。
start_delay:
无样本时的起步延迟(对齐 Scrapy AUTOTHROTTLE_START_DELAY:
首个响应到来前先用固定值)。默认 0.0(不拖慢冷启动)。
penalty_factor:
失败惩罚倍率的放大系数(> 1.0):每次失败乘它、每次成功除它。
默认 1.5。
max_penalty:
惩罚倍率封顶(>= 1.0)。默认 10.0。
max_domains:
域账本 LRU 上限(>= 1),默认 65536:超出时淘汰最久未反馈的域,
被淘汰域重新出现时等价于冷启动(EMA 从首样本起步、惩罚归 1)。
防止长时开放爬取海量唯一域名时 _domains 无上限增长。
并发边界:全部状态由单把 threading.Lock 保护,临界区为纯内存
纳秒级操作(字典读写 + 浮点运算,无 IO、无 await),且调用频率
受网络请求速率约束(每次下载才反馈一次)——锁竞争上界远低于分片锁
带来的复杂度收益,无需分片锁。
Example¶
from web_crawler.spider import AutoThrottle at = AutoThrottle(target_concurrency=2.0) at.note_response("example.com", 0.5, success=True) # ema=0.5 at.get_delay("example.com") # 0.5 / 2.0 0.25
源代码位于: src/web_crawler/spider/autothrottle.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
get_delay
¶
返回该域相邻请求的最小间隔(秒)。
无样本(或尚无成功样本)时返回 clamp(start_delay),否则返回
clamp(EMA / target_concurrency * penalty)。
源代码位于: src/web_crawler/spider/autothrottle.py
note_response
¶
向限速器反馈一次下载结果,并触碰该域的 LRU 位置。
成功样本纳入 EMA 并对称回落惩罚;失败样本不进 EMA(保持健康
延迟基准),只逐次放大惩罚。Spider 侧在每次真实下载(非中间件
短路)完成后调用,success 传 response.ok。
反馈使该域移到 LRU 末尾;max_domains 超限时最久未反馈的域
被淘汰,其重新出现时等价于冷启动(EMA 从首样本起步、惩罚归 1)。
Parameters¶
domain: 域名键(大小写不敏感;调用方保证同域同键)。 elapsed: 本次下载耗时(秒)。负值按 0 处理(防御时钟回拨)。 success: 是否成功(2xx/3xx 视为成功)。
源代码位于: src/web_crawler/spider/autothrottle.py
stats
¶
返回各域限速快照。
结构:{domain: {"ema_latency", "delay", "penalty",
"consecutive_failures", "samples"}}。ema_latency 在该域尚无
成功样本时为 None。
源代码位于: src/web_crawler/spider/autothrottle.py
BaseFetcher
¶
所有 fetcher 共享的配置基类。
子类(Fetcher、DynamicFetcher、StealthyFetcher)继承这些
选项与响应构建辅助方法,使每个 fetcher 都返回统一的 :class:Response。
源代码位于: src/web_crawler/fetchers/_base.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | |
CacheMiddleware
¶
Bases: DownloaderMiddleware
GET 响应磁盘缓存中间件(DownloaderMiddleware 协议)。
- 仅缓存 GET:其他 method 直接透传(不读不写缓存)。
- 磁盘存储:
cache_dir下每个条目两个文件——<sha256>.meta.json(URL / 时间戳 / 状态码 / headers / encoding)与<sha256>.body(zlib 压缩的响应体)。写入先落临时文件再os.replace原子替换, 并发读写不会见到半成品。 - TTL:
ttl秒后条目视为过期(未命中并被清理);None表示永久。 process_request命中且未过期时直接重建 Response 短路下载;offline=True时未命中抛 :class:IgnoreRequest(绝不发网络请求, 由引擎计入requests_ignored)。process_response在成功响应(2xx;cache_4xx时含 4xx)到达后 写缓存并透传。- 缓存键 =
method + 规范化 URL的 SHA-256:query 顺序无关、忽略 fragment 与 host/scheme 大小写、默认端口折叠。 ignore_lookup=True跳过查找强制走网络,但下载结果仍回写缓存 (缓存刷新模式);与offline同时设置时offline优先生效。- 线程模型:
threading.Lock只保护内存计数器;所有磁盘 IO 在锁外 执行(事件循环内的 worker 不会被慢速磁盘卡住),写入完整性由 "临时文件 +os.replace原子替换 + 先 body 后 meta 的落盘顺序" 独立保证,并发写同一 key 为 last-write-wins。
缓存命中只恢复 url / status / headers / encoding / content;
meta、screenshots 等运行期字段不参与缓存。
Parameters¶
cache_dir:
缓存目录(不存在时在首次写入时创建),默认 .web_crawler_cache。
ttl:
条目存活秒数;None 表示永久缓存。
offline:
离线回放模式:命中直接返回、未命中抛 :class:IgnoreRequest。
ignore_lookup:
每次请求都发网络(跳过缓存查找),但响应仍回写缓存。
cache_4xx:
额外缓存 4xx 响应(默认仅 2xx;5xx 永不缓存)。
max_body_size:
缓存条目解压后的响应体大小上限(字节),默认 64MB(64 * 1024 * 1024)。
64MB 的量级理由:Web 响应体绝大多数小于 10MB,64MB 已覆盖极端大
页面,同时把单条目读取 / 解压的内存峰值限制在可接受范围。读取时
压缩文件或解压输出超过该上限的条目按损坏处理(删除并视为未命中),
防止投毒的 .body(zlib bomb:几十 KB 压缩数据可解压出数 GB)
单次命中即耗尽内存。
Example¶
常规缓存(1 小时 TTL)::
class CachedSpider(Spider):
start_urls = ["https://quotes.toscrape.com/"]
middlewares = [CacheMiddleware(cache_dir=".web_crawler_cache", ttl=3600)]
def parse(self, response):
yield {"title": response.css_first("title").text}
离线回放(同目录已有缓存时不发任何网络请求)::
class ReplaySpider(Spider):
middlewares = [CacheMiddleware(cache_dir=".web_crawler_cache", offline=True)]
源代码位于: src/web_crawler/spider/cache.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 | |
cache_key
staticmethod
¶
计算缓存键:method + 规范化 URL 的 SHA-256 十六进制摘要。
源代码位于: src/web_crawler/spider/cache.py
process_request
¶
GET 请求先查缓存:命中且未过期时重建 Response 短路下载。
未命中(或非 GET / ignore_lookup)返回 None 放行下载;
offline=True 时未命中抛 :class:IgnoreRequest,由引擎计入
requests_ignored,保证离线模式下不发任何网络请求。
源代码位于: src/web_crawler/spider/cache.py
process_response
¶
成功响应(2xx;cache_4xx 时含 4xx)写缓存后透传。
源代码位于: src/web_crawler/spider/cache.py
purge
¶
清空磁盘缓存(仅删除本中间件命名模式的文件)并重置统计。
源代码位于: src/web_crawler/spider/cache.py
stats
¶
返回命中统计:hits / misses / stores 及磁盘条目数 entries。
hits / misses 只统计真正执行过缓存查找的 GET 请求(非 GET
与 ignore_lookup 跳过查找时不计入);stores 为实际落盘次数。
源代码位于: src/web_crawler/spider/cache.py
CamoufoxFetcher
¶
Bases: DynamicFetcher
用 Camoufox 反检测 Firefox 渲染的 :class:DynamicFetcher。
Parameters(在 :class:DynamicFetcher 之外新增的)¶
os:
指纹操作系统:"windows"/"macos"/"linux",或传入列表
随机挑选。None 时交给 Camoufox 决定。
humanize:
拟人化光标移动——True 或最大时长(秒)。
locale:
Intl API 的 locale,如 "en-US" 或 ["en-US", "fr-FR"]。
geoip:
True 时根据(代理)IP 自动推导地理位置/时区,也可传具体 IP
字符串。使用代理时建议开启。
block_webrtc:
彻底屏蔽 WebRTC(防止本机 IP 泄漏)。
window:
固定的 (宽, 高);保持 None 让 Camoufox 自选(固定尺寸本身
就是指纹特征)。
camoufox_options:
逃生口:直接透传给 Camoufox(...) 的额外关键字参数
(如 screen、fonts、fingerprint_preset、disable_coop)。
源代码位于: src/web_crawler/fetchers/camoufox.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | |
aclose
async
¶
关闭同步与异步两个 Camoufox 浏览器。
源代码位于: src/web_crawler/fetchers/camoufox.py
close
¶
关闭 Camoufox 浏览器及其托管的 Playwright driver(同步)。
源代码位于: src/web_crawler/fetchers/camoufox.py
ConfigError
¶
Bases: WebCrawlerError, ValueError
配置或参数校验失败(调用方传参错误,可立即修正的使用错误)。
典型触发场景:spider/autothrottle.py 与 fetchers/session.py
的数值范围校验、fetchers/proxy.py 的策略名、ai/llm.py 的
provider 注册、Spider 的 Request.url 非空校验、
ai/_reverse_actions.py 的动作类型 / selector 参数校验(均已接入)。
兼容基类 :class:ValueError:与「非法参数值」的 Python 惯例一致。
源代码位于: src/web_crawler/exceptions.py
DeepSeekProvider
¶
Bases: OpenAICompatibleProvider
DeepSeek 预置。默认 DeepSeek-V4.1-Flash,未传密钥时从环境变量
DEEPSEEK_API_KEY 读取。
源代码位于: src/web_crawler/ai/llm.py
DownloaderMiddleware
¶
下载中间件基类:在请求发出前/响应返回后介入下载流程。
- :meth:
process_request返回None放行下载;返回 :class:~web_crawler.response.Response直接短路(不再发请求); 抛 :class:IgnoreRequest丢弃该请求。 - :meth:
process_response收到下载结果,返回(可替换的)Response。
中间件按声明顺序依次执行;默认实现全部直通。
源代码位于: src/web_crawler/spider/spider.py
DropItem
¶
DupeFilter
¶
请求去重器:以 method + url + body 的 SHA1 指纹判定重复。
相比裸 URL 集合,同一 URL 的不同 method / body(如同一接口的
不同分页参数)不再被互相误杀;Spider 可通过构造参数
dupefilter 替换为自定义实现(如磁盘持久化版本)。
源代码位于: src/web_crawler/spider/spider.py
request_seen
¶
DynamicFetcher
¶
Bases: BaseFetcher
基于 Playwright 的 fetcher,先渲染 JavaScript 再返回 HTML。
Parameters¶
headless:
以 headless 模式运行 Chromium(cdp_url 接管时被忽略——浏览器
已由调用方自行启动)。
block_images:
中止图片请求以加速渲染。
disable_resources:
中止图片/媒体/字体/样式表请求,追求最快速度。
wait_selector:
可选的 CSS 选择器,导航完成后等待其出现。
wait_timeout:
wait_selector 与 networkidle 等待的超时时间(秒)。
network_idle:
导航后等待 networkidle 加载状态。
page_action:
页面加载后以 Playwright Page 为参数调用的回调,可在截取 HTML
前执行自定义交互(滚动、点击等)。
google_search:
将 referer 设为 https://www.google.com/,伪装流量来源。
storage_state:
登录态注入:原样透传给 browser.new_context 的同名参数,可传
状态文件路径(str/Path,如 "auth.json")或内联 dict
({"cookies": [...], "origins": [...]})。配合
save_storage_state 可实现"登录一次、后续任务复用"。不能与
user_data_dir 同时使用(持久化 profile 自带登录态)。
save_storage_state:
登录态导出路径:在每次渲染结束、以及 persistent context 关闭前,
调用 context.storage_state(path=...) 写盘。注意渲染 context 是
每次新建的,因此文件始终保存最近一次渲染的状态(含 cookies 与
localStorage;IndexedDB 不在内——需要完整保留请用 user_data_dir)。
user_data_dir:
持久化 profile 目录:改用 launch_persistent_context 启动,浏览器
的 cookie/localStorage/IndexedDB 全保留在磁盘。此时 context 即浏览器
会话、跨 fetch 复用(不再每次渲染新建/关闭 context);代理与视口在
启动时固化(screenshot_tiles 会按需调整当前 page 的视口宽度)。
不能与 cdp_url/storage_state 同时使用。
cdp_url:
CDP 接管已有浏览器(如用户自己启动的
chrome --remote-debugging-port=9222),经
chromium.connect_over_cdp 连接,优先级最高。headless 等
启动参数被忽略;close()/aclose() 仅断开连接(disconnect),不会
杀掉该浏览器进程——其生命周期归调用方管理。
登录态复用示例¶
from web_crawler import DynamicFetcher
第一步:手动登录一次并导出登录态(headless=False 便于人工登录)¶
with DynamicFetcher(headless=False, save_storage_state="auth.json") as f: ... f.fetch("https://example.com/login") # 可配合 page_action 自动填表
第二步:后续任务注入登录态,无需再次登录¶
with DynamicFetcher(storage_state="auth.json") as f: ... resp = f.fetch("https://example.com/dashboard")
CDP 接管示例::
# 终端先启动:chrome --remote-debugging-port=9222
with DynamicFetcher(cdp_url="http://localhost:9222") as f:
resp = f.fetch("https://example.com")
源代码位于: src/web_crawler/fetchers/dynamic.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 | |
aclose
async
¶
异步关闭同步与异步浏览器 / Playwright driver。
与 :meth:close 相同的模式差异(persistent 关闭前导出登录态、
CDP 仅 disconnect 不杀外部浏览器进程)。
源代码位于: src/web_crawler/fetchers/dynamic.py
async_fetch
async
¶
异步渲染 url 并返回 :class:Response。
源代码位于: src/web_crawler/fetchers/dynamic.py
async_get
async
¶
async_screenshot_tiles
async
¶
async_screenshot_tiles(
url: str,
*,
tile_height: int = 1024,
viewport_width: int = 875,
format: str = "png",
quality: int = 80,
max_tiles: int = 50,
) -> list[dict[str, Any]]
异步版 :meth:screenshot_tiles。
源代码位于: src/web_crawler/fetchers/dynamic.py
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | |
close
¶
关闭复用的同步浏览器并停止 Playwright driver(同步)。
对 async 句柄做 best-effort 清理:启动临时事件循环执行 aclose。 避免混用 async/sync 接口后 async browser 进程残留。
会话模式差异:
- 默认 launch:关闭 Chromium 进程;
- user_data_dir:persistent context 关闭即关浏览器,关闭前会把
最终登录态导出到 save_storage_state(若配置);
- cdp_url:仅断开 CDP 连接(disconnect),不杀用户自己的
浏览器进程——浏览器由外部启动,生命周期归调用方管理。
源代码位于: src/web_crawler/fetchers/dynamic.py
fetch
¶
用 headless 浏览器渲染 url 并返回 :class:Response。
源代码位于: src/web_crawler/fetchers/dynamic.py
get
¶
fetch 的动词统一别名:与 :class:~web_crawler.fetchers.Fetcher.get
对齐,使 Spider 等上层组件无需感知 fetcher 具体类型。
仅支持 GET 语义;带 data 等参数时退回 :meth:fetch 的默认行为。
源代码位于: src/web_crawler/fetchers/dynamic.py
screenshot_tiles
¶
screenshot_tiles(
url: str,
*,
tile_height: int = 1024,
viewport_width: int = 875,
format: str = "png",
quality: int = 80,
max_tiles: int = 50,
) -> list[dict[str, Any]]
渲染 url 并把整页切成固定高度的截图分块。
PixelRAG 风格的视觉分块:不从 HTML 提取文本,而是把渲染后的页面 截取为分块,可直接送入视觉语言模型做内容抽取或视觉嵌入。
Parameters¶
url:
要渲染并截图的页面 URL。
tile_height:
每个分块的高度(CSS 像素,默认 1024,与 PixelRAG 一致)。
viewport_width:
浏览器视口宽度(CSS 像素,默认 875,与 PixelRAG 一致)。
format:
截图图片格式:"png" 或 "jpeg"。
quality:
JPEG 质量(1-100),PNG 时忽略。
max_tiles:
单次调用最多生成的截图片数上限(防御超长页面/无限滚动导致的
内存与耗时失控);超过上限时截断并发出 RuntimeWarning。
Returns¶
list[dict]
每个分块形如 {index, total, b64: str, width, height},
其中 b64 是适合 VLM 输入的 base64 图片字符串。
源代码位于: src/web_crawler/fetchers/dynamic.py
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | |
ExtractionResult
dataclass
¶
:meth:AIExtractor.extract 调用的结果。
源代码位于: src/web_crawler/ai/extractor.py
FetchError
¶
Bases: WebCrawlerError, RuntimeError
网络抓取层失败:请求已发出但抓取流程无法完成。
典型触发场景:fetchers/fetcher.py 的重定向超限、
fetchers/dynamic.py 的 JS 渲染抓取失败、app/_crawler_core.py
的 stealth fetcher 不可用(均已接入)。
兼容基类 :class:RuntimeError:存量抓取层失败统一以
RuntimeError 表达,切换后 except RuntimeError 断言原样通过。
源代码位于: src/web_crawler/exceptions.py
Fetcher
¶
Bases: _FetcherCore
使用 curl_cffi TLS 伪装的隐身 HTTP fetcher(同步)。
安装了 curl_cffi 时(默认预期)持有 :class:curl_cffi.requests.Session
并伪装成真实浏览器。curl_cffi 缺失时回退到 httpx 并发出告警,
让调用者知道指纹隐身已禁用。
本类同时暴露异步方法(async_get / async_request),单个实例
即可同时服务同步与异步调用方。若需要纯异步 API 面,请使用
:class:AsyncFetcher。
Parameters¶
impersonate:
要伪装的 curl_cffi 浏览器指纹(默认 "chrome131")。
http2:
启用 HTTP/2(默认 True)。
max_redirects:
手动跟随重定向的最大跳数(默认 5)。每一跳都会重新校验 URL
scheme(SSRF 防护),跨源跳转会剥离 Authorization 请求头。
ja3_fingerprint:
可选的 JA3 TLS 指纹字符串,用于覆盖伪装预设(如自定义加密套件/
扩展顺序)。仅 curl_cffi 后端使用;回退 httpx 时忽略。
session_pool:
可选的 :class:~web_crawler.fetchers.session.SessionPool。启用时
每次请求从池中借出会话——指纹随会话轮换、空闲回收、连续失败淘汰,
请求(含 DNS 钉扎)完成后归还;None(默认)走单会话路径,
行为不变。传入的池会自动绑定本 fetcher 的会话工厂(超时/校验/
HTTP2 等配置随之生效,且 impersonate 参数退化为池降级时的
兜底指纹)。
源代码位于: src/web_crawler/fetchers/fetcher.py
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | |
aclose
async
¶
异步关闭同步与异步会话。
源代码位于: src/web_crawler/fetchers/fetcher.py
async_request
async
¶
close
¶
关闭底层同步会话。
异步会话无法在同步上下文中安全关闭(需要事件循环),请使用 aclose()
或 async with 上下文管理器来清理异步会话资源。
源代码位于: src/web_crawler/fetchers/fetcher.py
request
¶
IgnoreRequest
¶
ImageCaptchaSolver
¶
图片验证码破解器。
Parameters¶
provider: LLM Provider 实例。若为 None 或不支持 vision,则仅启用本地路径 (ddddocr OCR + Pillow/numpy 滑块匹配),点选验证码无法处理。 config: 配置;不传用默认值。
源代码位于: src/web_crawler/ai/image_captcha.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | |
solve_click
¶
识别点选验证码需要按顺序点击的元素坐标。
源代码位于: src/web_crawler/ai/image_captcha.py
solve_slider
¶
识别滑块缺口 x 坐标。
源代码位于: src/web_crawler/ai/image_captcha.py
solve_text
¶
识别图片中的文本字符(4-8 位字母数字)。
源代码位于: src/web_crawler/ai/image_captcha.py
InvalidStateError
¶
Bases: WebCrawlerError, RuntimeError
对象状态 / 前置条件不满足(方法在当前状态下不可调用)。
典型触发场景:parser/selector.py 的 save/retrieve/relocate 需要
adaptive=True、parser/storage.py 的 AdaptiveStorage 已关闭、
ai/recorder.py 未 load_script 就 replay(均已接入)。
兼容基类 :class:RuntimeError:命名对齐 asyncio.InvalidStateError
惯例,同时保持 RuntimeError 兼容以不破坏既有断言。
源代码位于: src/web_crawler/exceptions.py
ItemPipeline
¶
item 管道基类:回调产出的每条 item 依次经过各管道。
:meth:process_item 返回变换后的 item;返回 None 或抛
:class:DropItem 丢弃该条。
源代码位于: src/web_crawler/spider/spider.py
LLMMessage
dataclass
¶
单条聊天消息(role 取 system/user/assistant 之一)。
content 可以是纯文本字符串,也可以是 OpenAI 多模态消息内容列表
([{"type": "text", "text": "..."}, {"type": "image_url", "image_url": {...}}]),
用于 Vision-LLM 场景。to_dict 透传该结构。
源代码位于: src/web_crawler/ai/llm.py
text
classmethod
¶
vision
classmethod
¶
vision(
role: str,
text: str,
image_b64: str,
*,
mime: str = "image/png",
detail: str = "auto",
) -> LLMMessage
便捷构造带图片的多模态消息(OpenAI vision 格式)。
image_b64 是不带 data: 前缀的 base64 字符串。
源代码位于: src/web_crawler/ai/llm.py
LLMProvider
¶
Bases: Protocol
所有供应商都满足的结构化类型。
源代码位于: src/web_crawler/ai/llm.py
LLMResponse
dataclass
¶
归一化的 chat-completion 结果。
源代码位于: src/web_crawler/ai/llm.py
OpenAICompatibleProvider
¶
面向任意 OpenAI 兼容 /chat/completions 端点的供应商。
Parameters¶
model:
请求体中发送的模型名。
api_key:
Bearer token。缺省时回退到 api_key_env 环境变量。
base_url:
API 根地址,例如 https://api.deepseek.com/v1。
timeout:
单次请求超时(秒)。
default_headers:
合并进每个请求的额外 header。
源代码位于: src/web_crawler/ai/llm.py
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | |
achat
async
¶
achat(
messages: Sequence[str | LLMMessage | dict[str, str]]
| str,
*,
temperature: float = 0.2,
max_tokens: int | None = None,
response_format: dict[str, Any] | None = None,
**kwargs: Any,
) -> LLMResponse
:meth:chat 的异步版本。
源代码位于: src/web_crawler/ai/llm.py
aclose
async
¶
chat
¶
chat(
messages: Sequence[str | LLMMessage | dict[str, str]]
| str,
*,
temperature: float = 0.2,
max_tokens: int | None = None,
response_format: dict[str, Any] | None = None,
**kwargs: Any,
) -> LLMResponse
调用 chat-completions 端点并返回 :class:LLMResponse。
源代码位于: src/web_crawler/ai/llm.py
close
¶
complete
¶
一次性辅助方法:仅返回 prompt 对应的助手文本。
源代码位于: src/web_crawler/ai/llm.py
ParseError
¶
Bases: WebCrawlerError, ValueError
解析层错误:输入内容 / 持久化数据不符合预期的结构或格式。
典型触发场景:parser/visual.py 的 tiles 参数、spider/cache.py
的缓存 meta 版本不符与 _read_body 解压超限 / 截断流(均已接入)。
兼容基类 :class:ValueError:解析层失败多为「内容不合法」,
与既有 ValueError 断言保持兼容。
源代码位于: src/web_crawler/exceptions.py
ProxyPool
¶
线程安全的轮换代理池,按代理跟踪失败情况。
Parameters¶
proxies:
初始代理 URL 列表(如 "http://user:pass@host:port")。
strategy:
"round_robin"(默认)按顺序轮询代理;"random" 在可用代理中
均匀随机挑选。
max_failures:
连续失败多少次后代理进入冷却。
cooldown:
冷却中的代理被跳过的秒数,之后重新尝试。
源代码位于: src/web_crawler/fetchers/proxy.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
add
¶
available_count
¶
get
¶
返回下一个可用代理 URL;池为空时返回 None。
源代码位于: src/web_crawler/fetchers/proxy.py
mark_failed
¶
记录 proxy 的一次失败;累计达到 max_failures 次后进入冷却。
源代码位于: src/web_crawler/fetchers/proxy.py
mark_success
¶
remove
¶
Request
dataclass
¶
一个已调度的请求。
callback 是 :class:Spider 子类上的方法名(默认 "parse")。
priority 值越大越先处理。meta 会透传到 response.meta,
供回调传递状态。
源代码位于: src/web_crawler/spider/spider.py
Response
¶
带选择器助手的归一化抓取响应。
源代码位于: src/web_crawler/response.py
RobotsPolicy
¶
带按主机缓存的小型 robots.txt 闸门(仅用标准库)。
fetch_text 由调用方注入:接收 robots.txt URL、返回其文本内容;
拉取失败(网络错误、超时)时按空规则解析,即保守视为全允许。
源代码位于: src/web_crawler/robots.py
crawl_delay
¶
返回 url 所在站点 robots.txt 为本 UA 声明的 Crawl-delay(秒)。
复用 :meth:_parser_for 的按主机缓存(与 :meth:allowed 共享,
同主机至多一次 robots.txt 外呼)。多 UA 匹配语义见
:func:_first_crawl_delay:具体 UA 组优先命中,含 * 的组作为
兜底;纯数字以外的声明(负数、小数、文本)一律忽略。
以下情形均返回 None(调用方据此视为"站点未施加额外延迟要求"):
站点未声明 Crawl-delay、声明值无效、robots.txt 拉取失败(按空规则
解析,保守视为允许故同样无延迟)。
fetch_text 注入模式与 :meth:allowed 一致;缺省时回退模块级
:func:fetch_robots_text(运行时解析,便于测试整体替换)。
源代码位于: src/web_crawler/robots.py
ScrapeResult
dataclass
¶
:meth:AIScrapeAgent.scrape 调用的结果。
源代码位于: src/web_crawler/ai/agent.py
Selector
¶
包装 lxml 元素树的 Scrapling 风格选择器。
源代码位于: src/web_crawler/parser/selector.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | |
css
¶
css(
selector: str,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> ResultList[Any]
按 CSS 选择器选取元素,可选自适应兜底。
支持 Scrapling 风格的 ::attr(name) 伪元素:若选择器以
::attr(name) 结尾,则返回匹配元素的属性值列表
(ResultList[TextHandler],属性缺失时为空字符串),
否则返回 ResultList[Selector]。
源代码位于: src/web_crawler/parser/selector.py
css_first
¶
css_first(
selector: str,
default: Any = None,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> Any
首个匹配,无匹配时返回 default。
若选择器带 ::attr(name),返回属性值(TextHandler),否则返回
Selector。
性能:与 self.css(selector).first 语义一致,但只包装首个匹配
元素,不为丢弃其余 N-1 个匹配逐个构造 Selector。
源代码位于: src/web_crawler/parser/selector.py
find_by_regex
¶
查找直接文本匹配正则 query 的元素。
对齐 Scrapling 的 find_by_regex:用编译好的或字符串形式的模式
扫描每个元素的直接文本。
源代码位于: src/web_crawler/parser/selector.py
find_by_text
¶
find_by_text(
text: str,
*,
exact: bool = False,
case_sensitive: bool = False,
) -> ResultList[Selector]
查找直接文本匹配 text 的元素。
源代码位于: src/web_crawler/parser/selector.py
find_similar
¶
find_similar(
reference: Selector | _Element,
*,
threshold: float = 0.5,
limit: int = 10,
) -> ResultList[Selector]
查找与 reference 结构相似的元素。
源代码位于: src/web_crawler/parser/selector.py
get_all_text
¶
get_all_text(
*,
separator: str = " ",
strip: bool = False,
ignore_tags: tuple[str, ...] = ("script", "style"),
) -> TextHandler
返回所有后代元素文本的拼接结果。
对齐 Scrapling 的 get_all_text:遍历子树,默认跳过
script/style,用 separator 连接文本。
性能:沿用逐元素遍历(而非 itertext),因为被跳过的
ignore_tags 元素其 tail 也必须一并丢弃,itertext
无法表达该语义;此处仅做循环内 append 局部化与空串快速路径。
源代码位于: src/web_crawler/parser/selector.py
prettify
¶
re
¶
返回本元素文本内容的全部正则匹配。
对齐 Scrapling 的 Adaptor.re:搜索元素的完整文本并返回匹配字符
串列表(模式含捕获组时返回各组内容)。
源代码位于: src/web_crawler/parser/selector.py
re_first
¶
re_first(
regex: str | Pattern[str],
default: str | None = None,
*,
clean_match: bool = False,
) -> str | None
返回本元素文本的首个正则匹配,无匹配时返回 default。
源代码位于: src/web_crawler/parser/selector.py
relocate
¶
relocate(
element: dict[str, Any] | Selector | _Element,
threshold: float = 0.5,
) -> ResultList[Selector]
按结构相似度在当前文档中重新定位 element。
对齐 Scrapling 的 Selector.relocate:给定先前存储的指纹
(:meth:retrieve 返回的 dict、:class:Selector 或原始 lxml 元素),
在本文档中找出最匹配的元素。
返回重定位选择器构成的 :class:ResultList(无候选超过 threshold
时为空)。
源代码位于: src/web_crawler/parser/selector.py
retrieve
¶
返回 identifier 存储的指纹记录,没有时为 None。
对齐 Scrapling 的 Selector.retrieve:取出先前保存的指纹
(tag/text/fingerprint/url),供人工检查或自定义匹配。
源代码位于: src/web_crawler/parser/selector.py
save
¶
把 element 的指纹以 identifier 持久化。
对齐 Scrapling 的 Selector.save:让调用者显式存储元素的结构
指纹,供之后自适应重定位使用,而不必依赖选择时的 auto_save=True。
源代码位于: src/web_crawler/parser/selector.py
xpath
¶
xpath(
selector: str,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> ResultList[Any]
按 XPath 选取元素,可选自适应兜底。
支持 Scrapling 风格的 ::attr(name) 伪元素(追加在 XPath 末尾)。
若未使用伪元素,建议直接用原生 XPath @attr 语法。
源代码位于: src/web_crawler/parser/selector.py
xpath_first
¶
xpath_first(
selector: str,
default: Any = None,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> Any
首个匹配,无匹配时返回 default。支持 ::attr(name) 伪元素。
性能:与 self.xpath(selector).first 语义一致,但只包装首个
元素结果,不为丢弃其余 N-1 个匹配逐个构造 Selector。
源代码位于: src/web_crawler/parser/selector.py
SessionPool
¶
带指纹轮换与健康管理的会话池(同步 + 异步双池,线程安全)。
Parameters¶
fingerprints:
impersonate 目标列表(按序轮换分配给新建会话);None(默认)
使用 :data:DEFAULT_FINGERPRINTS。curl_cffi 不可用时整个指纹
维度被跳过(降级为纯 httpx 会话池化)。
strategy:
"round_robin"(默认)按序轮换指纹;"random" 随机挑选。
max_size:
池缓存的会话数上限(同步/异步两套缓存各自适用)。瞬时并发超过
上限时新建临时会话应急,归还时直接关闭。
max_idle:
空闲会话的回收秒数;空闲超过该值的会话在下次取用时逐出关闭。
max_failures:
连续失败多少次后会话被淘汰(对应 ProxyPool 的 max_failures)。
prewarm:
构造时预先建好的同步会话数;异步预热在事件循环内进行,用
await prewarm_async()。
session_factory:
同步会话工厂 Callable[[str | None], Any]——入参为该会话的
指纹(降级时 None),返回后端会话。None 用内置默认工厂。
:class:~web_crawler.fetchers.fetcher.Fetcher 构造时会自动绑定
自己的工厂(见 :meth:bind_factories)。
async_session_factory:
异步会话工厂(签名同上)。None 用内置默认工厂。
clock:
单调时钟(默认 time.monotonic);可注入假时钟测试空闲回收。
源代码位于: src/web_crawler/fetchers/session.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 | |
aclose
async
¶
关闭全部异步会话(同步会话请用 close();语义同上)。
源代码位于: src/web_crawler/fetchers/session.py
acquire
¶
借出一个同步会话:优先复用空闲会话,其次新建(池满则临时新建)。
永不阻塞(对齐 ProxyPool get())。借出的会话用完必须
:meth:release 归还;取用时指纹已就绪(会话创建即绑定指纹)。
源代码位于: src/web_crawler/fetchers/session.py
acquire_async
async
¶
借出一个异步会话(事件循环内无锁原子;语义同 :meth:acquire)。
必须在事件循环内调用;跨循环复用同一池时旧条目自动弃置重建(不支 持多个事件循环并发使用同一池)。
源代码位于: src/web_crawler/fetchers/session.py
bind_factories
¶
bind_factories(
*,
session_factory: Callable[[str | None], Any]
| None = None,
async_session_factory: Callable[[str | None], Any]
| None = None,
) -> None
为尚未配置的工厂槽位绑定会话工厂(first-wins,不覆盖已有绑定)。
:class:~web_crawler.fetchers.fetcher.Fetcher /
:class:~web_crawler.fetchers.fetcher.AsyncFetcher 构造时会自动调
用:把自己按指纹构建会话的方法绑进池,让池化会话继承 fetcher 的
超时/校验/HTTP2 等配置。多个 fetcher 共享同一池时以第一个绑定者
为准——建议共享者配置一致,或构造池时显式传入工厂。
源代码位于: src/web_crawler/fetchers/session.py
close
¶
关闭全部同步会话(异步会话请用 await aclose())。
调用前应确保没有在途借出(借出中的会话会被一并关闭,后续归还按 no-op 处理)。关闭后池仍可继续使用(缓存清空后按需新建)。
源代码位于: src/web_crawler/fetchers/session.py
mark_failed
¶
记录借出中会话的一次失败;累计达阈值标记 stale(归还时淘汰)。
仅作用于借出中的句柄——空闲会话的淘汰由归还路径
(release(success=False) 的连续失败累计)完成。未知/已归还的
句柄 no-op(对齐 ProxyPool 对未知代理的宽容语义)。
线程安全语义:同步与异步句柄的 failures/stale 读-改-写都
在 threading.Lock 内完成——GIL 下 += 非原子,锁外更新在
多线程并发调用(如线程池)时会丢失计数;锁内为纯内存纳秒级操作,
事件循环线程调用无感知。注意与 release_async(事件循环内无锁
更新)并发标记同一异步句柄属于异步侧单循环设计之外的用法,调用方
需避免(见模块 docstring 的单事件循环约束)。
源代码位于: src/web_crawler/fetchers/session.py
mark_success
¶
清零会话的连续失败计数并解除 stale 标记(对齐 ProxyPool.mark_success)。
仅对本池管理的句柄(同步/异步任一活跃或空闲集合中)生效,未知/
已出池句柄 no-op——与 :meth:mark_failed 的宽容语义对称。
源代码位于: src/web_crawler/fetchers/session.py
prewarm_async
async
¶
在当前事件循环内预先建好 count 个异步会话(默认构造参数 prewarm)。
异步会话绑定创建它的事件循环,预热必须在目标循环内进行(构造参数
prewarm 只预热同步会话)。
源代码位于: src/web_crawler/fetchers/session.py
release
¶
归还借出的同步会话;请求失败时传 success=False 累计健康计数。
连续失败达到 max_failures 次(或已被 :meth:mark_failed 标记
stale)的会话直接关闭淘汰,下次 :meth:acquire 新建重建(指纹轮换
序继续推进);临时会话(池满应急新建)用完即关。未知/已归还/异步
句柄宽容 no-op(对齐 ProxyPool 对未知代理的宽容语义)。
会话关闭在锁外执行:socket 关闭可能毫秒级阻塞,持锁关闭会放大高
并发借还下的锁竞争(对齐 :meth:close 的既有模式——锁内只更新
状态并收集待关句柄,锁外统一执行关闭)。
源代码位于: src/web_crawler/fetchers/session.py
release_async
async
¶
归还借出的异步会话(语义同 :meth:release)。
源代码位于: src/web_crawler/fetchers/session.py
stats
¶
返回池状态快照(活跃/空闲/指纹分布/淘汰计数)。
同步侧在锁内做一次惰性空闲回收(对齐 ProxyPool
available_count 的惰性冷却清理)。异步侧集合可能被事件循环
线程并发修改(acquire_async/release_async 的无锁设计):
必须先用 list() 做一次原子快照(纯 C 层拷贝、不释放 GIL)再
迭代——若在锁外用 Python 层 for 循环逐句柄迭代 set,尺寸被并发
修改会抛 RuntimeError: Set changed size during iteration。
快照后数值可能瞬时略滞后(诊断用途可接受)。异步句柄的锁外关闭
(空闲回收)与同步侧统一:锁内收集、锁外执行。
源代码位于: src/web_crawler/fetchers/session.py
Spider
¶
用户 spider 的基类。
子类定义 :attr:start_urls(或重写 :meth:start_requests)与一个
parse 回调。回调可以 yield 更多 :class:Request 对象
(会被调度)或任意其他对象(视为抓取到的 item 并收集)。
源代码位于: src/web_crawler/spider/spider.py
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | |
allowed
¶
url 的 host 在允许范围内时返回 True(忽略端口与 userinfo)。
源代码位于: src/web_crawler/spider/spider.py
async_run
async
¶
async_run(
*,
max_requests: int | None = None,
state_file: str | Path | None = None,
resume: bool = False,
) -> list[Any]
异步版本:并发抓取,上限为 :attr:max_concurrency。
委托给 :meth:stream,核心 worker 循环只实现一份。
源代码位于: src/web_crawler/spider/spider.py
parse
¶
pause
¶
run
¶
run(
*,
max_requests: int | None = None,
state_file: str | Path | None = None,
resume: bool = False,
) -> list[Any]
同步运行 spider 并返回收集到的 item。
Parameters¶
max_requests:
本次运行发出请求数的硬上限。
state_file:
用于暂停/恢复的 JSON 文件路径。resume 为 True 且文件存在时,
队列与已见集合会被恢复。
resume:
state_file 存在时从其恢复。
源代码位于: src/web_crawler/spider/spider.py
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 | |
start_requests
¶
stream
async
¶
stream(
*,
max_requests: int | None = None,
state_file: str | Path | None = None,
resume: bool = False,
) -> AsyncIterator[Any]
异步流式产出抓取到的 item,适合长爬取与实时管道。
调度为持续流式:并发槽位空出即取队首请求派发,慢请求不会 阻塞后续请求的调度(无整批 barrier)。
用法::
async for item in spider.stream():
process(item)
与 :meth:async_run 不同,不把所有 item 缓存在内存里,而是
每抓到一条就 yield 出去(按完成顺序)。
源代码位于: src/web_crawler/spider/spider.py
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | |
SpiderError
¶
Bases: WebCrawlerError
致命 spider 引擎错误(回调错误、状态损坏)时抛出。
统一异常体系成员(第三批接入):SpiderError ⊂ WebCrawlerError,
调用方可用 except WebCrawlerError 统一收口库内错误。
SpiderStats
dataclass
¶
轻量运行统计。
源代码位于: src/web_crawler/spider/spider.py
StealthyFetcher
¶
Bases: DynamicFetcher
用隐身、拟人化与 Cloudflare 处理加固的 :class:DynamicFetcher。
默认值面向隐身调优:为提速屏蔽图片,并把 referer 伪装为 Google。
设置 humanize=True 可加入随机鼠标移动与延时;设置
solve_cloudflare=True 可尽力等待并点击 Cloudflare 质询过渡页。
源代码位于: src/web_crawler/fetchers/stealthy.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
async_fetch
async
¶
UnsafeTargetError
¶
Bases: WebCrawlerError, ValueError
SSRF 门禁拒绝:目标 host / URL 指向不安全地址。
语义:私网、环回、链路本地(含云元数据 169.254.169.254 /
100.100.100.200)、CGNAT、组播、未指定地址,localhost /
*.local 等静态黑名单主机名,或 DNS 解析落入拒绝段的目标。
典型触发场景:_ssrf.validate_url_host、fetchers/_pin.py 的
TOCTOU 钉扎拦截、重定向跳向不安全 host(均已接入)。
兼容基类 :class:ValueError:存量 except ValueError /
pytest.raises(ValueError) 断言在 raise 类型切换后原样通过。
源代码位于: src/web_crawler/exceptions.py
VisualExtractor
¶
用 VLM(OpenAI 兼容视觉 API)从截图分块中提取内容。
Parameters¶
api_key:
视觉模型服务的 API key。
base_url:
OpenAI 兼容的 base URL(如 https://api.deepseek.com/v1 或
https://dashscope.aliyuncs.com/compatible-mode/v1)。
model:
支持视觉的模型名(如 gpt-4o、qwen-vl-max、
qwen3.7-plus、deepseek-chat)。
max_tokens:
最大输出 token 数(默认 4096)。
timeout:
HTTP 请求超时秒数(默认 120)。
源代码位于: src/web_crawler/parser/visual.py
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
extract
¶
extract(
tiles: list[dict[str, Any]],
prompt: str = "Please extract the main content from this web page screenshot. Preserve headings, paragraph structure, table data (as markdown tables), lists, and key numbers. If it is an article, summarize the key points. If it contains data tables or charts, describe the data accurately.",
*,
temperature: float = 0.3,
max_tiles: int = 20,
) -> str
通过 VLM 从截图分块提取结构化文本内容。
Parameters¶
tiles:
:meth:DynamicFetcher.screenshot_tiles 返回的分块 dict 列表,
每个必须含 b64(base64 编码图片)。
prompt:
给 VLM 的指令,说明要提取什么。
temperature:
采样温度(0.0–2.0)。越低越确定。
max_tiles:
最多发送的分块数(设上限避免 token 溢出)。
Returns¶
str VLM 提取出的文本内容。
源代码位于: src/web_crawler/parser/visual.py
extract_with_client
¶
extract_with_client(
tiles: list[dict[str, Any]],
prompt: str,
*,
client: Any = None,
temperature: float = 0.3,
max_tiles: int = 20,
) -> str
类似 :meth:extract,但接受现成的 OpenAI client 实例。
传入 openai.OpenAI 或 openai.AsyncOpenAI client 以复用现有
连接池。需要安装 openai 包。
Parameters¶
client:
openai.OpenAI 实例。为 None 时回退到基于 urllib 的
:meth:extract。
源代码位于: src/web_crawler/parser/visual.py
WebCrawlerError
¶
Bases: Exception
web-crawler 库内所有异常的根基类。
语义:仅作 isinstance / except 的统一收口,生产代码不直接
raise 它——具体错误一律抛更精确的子类。
典型用法::
try:
validate_url_host(url)
except WebCrawlerError:
... # 库自身的任何错误,与环境错误精确区分
源代码位于: src/web_crawler/exceptions.py
__getattr__
¶
首次访问时惰性导入公开符号(Scrapling 风格)。
这样 import web_crawler 保持轻量,只用到解析器的用户不必安装
playwright/curl_cffi。
源代码位于: src/web_crawler/__init__.py
available_providers
¶
compute_fingerprint
¶
为 element 计算可 JSON 序列化的结构指纹。
源代码位于: src/web_crawler/parser/adaptive.py
get_provider
¶
实例化一个已注册的供应商(默认:DeepSeek / DeepSeek-V4.1-Flash)。
其余关键字参数(model、api_key、base_url 等)会透传给
供应商构造器。
源代码位于: src/web_crawler/ai/llm.py
register_provider
¶
similarity_score
¶
返回两个指纹 JSON 字符串之间 0..1 的相似度得分。
源代码位于: src/web_crawler/parser/adaptive.py
Fetcher¶
Fetcher 是主力 HTTP fetcher,基于 curl_cffi 重放真实浏览器的 TLS/JA3 指纹与
HTTP/2 帧序;curl_cffi 缺失时自动降级到 httpx(带 warning,无指纹能力)。
支持 impersonate 浏览器预设、ja3_fingerprint 细粒度 TLS 指纹定制与
max_redirects(默认 5)重定向跳数上限。
web_crawler.fetchers.fetcher.Fetcher
¶
Bases: _FetcherCore
使用 curl_cffi TLS 伪装的隐身 HTTP fetcher(同步)。
安装了 curl_cffi 时(默认预期)持有 :class:curl_cffi.requests.Session
并伪装成真实浏览器。curl_cffi 缺失时回退到 httpx 并发出告警,
让调用者知道指纹隐身已禁用。
本类同时暴露异步方法(async_get / async_request),单个实例
即可同时服务同步与异步调用方。若需要纯异步 API 面,请使用
:class:AsyncFetcher。
Parameters¶
impersonate:
要伪装的 curl_cffi 浏览器指纹(默认 "chrome131")。
http2:
启用 HTTP/2(默认 True)。
max_redirects:
手动跟随重定向的最大跳数(默认 5)。每一跳都会重新校验 URL
scheme(SSRF 防护),跨源跳转会剥离 Authorization 请求头。
ja3_fingerprint:
可选的 JA3 TLS 指纹字符串,用于覆盖伪装预设(如自定义加密套件/
扩展顺序)。仅 curl_cffi 后端使用;回退 httpx 时忽略。
session_pool:
可选的 :class:~web_crawler.fetchers.session.SessionPool。启用时
每次请求从池中借出会话——指纹随会话轮换、空闲回收、连续失败淘汰,
请求(含 DNS 钉扎)完成后归还;None(默认)走单会话路径,
行为不变。传入的池会自动绑定本 fetcher 的会话工厂(超时/校验/
HTTP2 等配置随之生效,且 impersonate 参数退化为池降级时的
兜底指纹)。
源代码位于: src/web_crawler/fetchers/fetcher.py
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | |
aclose
async
¶
异步关闭同步与异步会话。
源代码位于: src/web_crawler/fetchers/fetcher.py
async_request
async
¶
close
¶
关闭底层同步会话。
异步会话无法在同步上下文中安全关闭(需要事件循环),请使用 aclose()
或 async with 上下文管理器来清理异步会话资源。
源代码位于: src/web_crawler/fetchers/fetcher.py
request
¶
web_crawler.fetchers.fetcher.AsyncFetcher
¶
Bases: _FetcherCore
纯异步隐身 HTTP fetcher(对齐 Scrapling 的 AsyncFetcher)。
与 :class:Fetcher 共享全部配置、后端选择与重试逻辑,但只暴露
异步 API。没有同步 get/post 方法,意图明确且绝不创建同步会话。
异步应用中使用它,可避免同步调用意外阻塞事件循环。构造参数与
:class:Fetcher 完全一致——包括可选的 session_pool(异步借还
走池的 acquire_async / release_async)。
源代码位于: src/web_crawler/fetchers/fetcher.py
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 | |
aclose
async
¶
异步关闭异步会话(同步会话从不创建)。
源代码位于: src/web_crawler/fetchers/fetcher.py
request
async
¶
Selector¶
Selector 是基于 lxml + cssselect 的自适应解析器,对齐 Scrapling Adaptor API。
支持 CSS / XPath / 正则 / 文本查找,完整 DOM 遍历,以及元素指纹 + 相似度重定位。
web_crawler.parser.selector.Selector
¶
包装 lxml 元素树的 Scrapling 风格选择器。
源代码位于: src/web_crawler/parser/selector.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | |
css
¶
css(
selector: str,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> ResultList[Any]
按 CSS 选择器选取元素,可选自适应兜底。
支持 Scrapling 风格的 ::attr(name) 伪元素:若选择器以
::attr(name) 结尾,则返回匹配元素的属性值列表
(ResultList[TextHandler],属性缺失时为空字符串),
否则返回 ResultList[Selector]。
源代码位于: src/web_crawler/parser/selector.py
css_first
¶
css_first(
selector: str,
default: Any = None,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> Any
首个匹配,无匹配时返回 default。
若选择器带 ::attr(name),返回属性值(TextHandler),否则返回
Selector。
性能:与 self.css(selector).first 语义一致,但只包装首个匹配
元素,不为丢弃其余 N-1 个匹配逐个构造 Selector。
源代码位于: src/web_crawler/parser/selector.py
find_by_regex
¶
查找直接文本匹配正则 query 的元素。
对齐 Scrapling 的 find_by_regex:用编译好的或字符串形式的模式
扫描每个元素的直接文本。
源代码位于: src/web_crawler/parser/selector.py
find_by_text
¶
find_by_text(
text: str,
*,
exact: bool = False,
case_sensitive: bool = False,
) -> ResultList[Selector]
查找直接文本匹配 text 的元素。
源代码位于: src/web_crawler/parser/selector.py
find_similar
¶
find_similar(
reference: Selector | _Element,
*,
threshold: float = 0.5,
limit: int = 10,
) -> ResultList[Selector]
查找与 reference 结构相似的元素。
源代码位于: src/web_crawler/parser/selector.py
get_all_text
¶
get_all_text(
*,
separator: str = " ",
strip: bool = False,
ignore_tags: tuple[str, ...] = ("script", "style"),
) -> TextHandler
返回所有后代元素文本的拼接结果。
对齐 Scrapling 的 get_all_text:遍历子树,默认跳过
script/style,用 separator 连接文本。
性能:沿用逐元素遍历(而非 itertext),因为被跳过的
ignore_tags 元素其 tail 也必须一并丢弃,itertext
无法表达该语义;此处仅做循环内 append 局部化与空串快速路径。
源代码位于: src/web_crawler/parser/selector.py
prettify
¶
re
¶
返回本元素文本内容的全部正则匹配。
对齐 Scrapling 的 Adaptor.re:搜索元素的完整文本并返回匹配字符
串列表(模式含捕获组时返回各组内容)。
源代码位于: src/web_crawler/parser/selector.py
re_first
¶
re_first(
regex: str | Pattern[str],
default: str | None = None,
*,
clean_match: bool = False,
) -> str | None
返回本元素文本的首个正则匹配,无匹配时返回 default。
源代码位于: src/web_crawler/parser/selector.py
relocate
¶
relocate(
element: dict[str, Any] | Selector | _Element,
threshold: float = 0.5,
) -> ResultList[Selector]
按结构相似度在当前文档中重新定位 element。
对齐 Scrapling 的 Selector.relocate:给定先前存储的指纹
(:meth:retrieve 返回的 dict、:class:Selector 或原始 lxml 元素),
在本文档中找出最匹配的元素。
返回重定位选择器构成的 :class:ResultList(无候选超过 threshold
时为空)。
源代码位于: src/web_crawler/parser/selector.py
retrieve
¶
返回 identifier 存储的指纹记录,没有时为 None。
对齐 Scrapling 的 Selector.retrieve:取出先前保存的指纹
(tag/text/fingerprint/url),供人工检查或自定义匹配。
源代码位于: src/web_crawler/parser/selector.py
save
¶
把 element 的指纹以 identifier 持久化。
对齐 Scrapling 的 Selector.save:让调用者显式存储元素的结构
指纹,供之后自适应重定位使用,而不必依赖选择时的 auto_save=True。
源代码位于: src/web_crawler/parser/selector.py
xpath
¶
xpath(
selector: str,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> ResultList[Any]
按 XPath 选取元素,可选自适应兜底。
支持 Scrapling 风格的 ::attr(name) 伪元素(追加在 XPath 末尾)。
若未使用伪元素,建议直接用原生 XPath @attr 语法。
源代码位于: src/web_crawler/parser/selector.py
xpath_first
¶
xpath_first(
selector: str,
default: Any = None,
*,
auto_save: bool = False,
adaptive: bool = False,
threshold: float = 0.5,
) -> Any
首个匹配,无匹配时返回 default。支持 ::attr(name) 伪元素。
性能:与 self.xpath(selector).first 语义一致,但只包装首个
元素结果,不为丢弃其余 N-1 个匹配逐个构造 Selector。
源代码位于: src/web_crawler/parser/selector.py
ReverseAgent¶
ReverseAgent 是 JS 逆向 Agent 主循环,编排浏览器、Hook、AI 分析器、验证码处理,
形成"观察-思考-行动"的自主循环。同步入口 run 与异步入口 arun 共享同一套配置。
web_crawler.ai.reverse_agent.ReverseAgent
¶
Bases: ActionExecutor
JS 逆向 Agent 主循环。
编排浏览器、Hook、AI 分析器、验证码处理,形成"观察-思考-行动"的自主循环。
同步入口 :meth:run 与异步入口 :meth:arun 共享同一套配置与分析器,
适用于定位前端动态生成的加密参数(Anti-Content / X-Bogus / _signature 等)。
动作执行能力(_act_async / _do_*_async 等)来自
:class:~web_crawler.ai._reverse_actions.ActionExecutor mixin
(纯移动拆分,行为与异常消息零变化)。
源代码位于: src/web_crawler/ai/reverse_agent.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 | |
aclose
async
¶
arun
async
¶
异步版本的主循环。与 :meth:run 行为一致,但所有 IO 都走 async。
源代码位于: src/web_crawler/ai/reverse_agent.py
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 | |
checkpoints_snapshot
¶
读取已保存的 checkpoint 列表(step + path),供结果汇总使用。
源代码位于: src/web_crawler/ai/reverse_agent.py
close
¶
run
¶
同步入口:在临时事件循环中驱动 :meth:arun(async 为唯一实现)。
不能在已运行的事件循环内调用(asyncio.run 不可嵌套);
async 上下文请直接 await agent.arun(...)。
源代码位于: src/web_crawler/ai/reverse_agent.py
web_crawler.ai.reverse_agent.ReverseAgentConfig
dataclass
¶
JS 逆向 Agent 配置。
源代码位于: src/web_crawler/ai/_reverse_support.py
LLM Provider¶
LLM provider 抽象层,OpenAI 兼容 chat-completions 接口。默认 DeepSeekProvider
指向 DeepSeek-V4.1-Flash。
web_crawler.ai.llm.LLMProvider
¶
Bases: Protocol
所有供应商都满足的结构化类型。
源代码位于: src/web_crawler/ai/llm.py
web_crawler.ai.llm.DeepSeekProvider
¶
Bases: OpenAICompatibleProvider
DeepSeek 预置。默认 DeepSeek-V4.1-Flash,未传密钥时从环境变量
DEEPSEEK_API_KEY 读取。
源代码位于: src/web_crawler/ai/llm.py
Spider¶
回调驱动的爬虫框架,支持优先级调度、域名过滤、URL 去重、JSON 暂停/续跑。
web_crawler.spider.spider.Spider
¶
用户 spider 的基类。
子类定义 :attr:start_urls(或重写 :meth:start_requests)与一个
parse 回调。回调可以 yield 更多 :class:Request 对象
(会被调度)或任意其他对象(视为抓取到的 item 并收集)。
源代码位于: src/web_crawler/spider/spider.py
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | |
allowed
¶
url 的 host 在允许范围内时返回 True(忽略端口与 userinfo)。
源代码位于: src/web_crawler/spider/spider.py
async_run
async
¶
async_run(
*,
max_requests: int | None = None,
state_file: str | Path | None = None,
resume: bool = False,
) -> list[Any]
异步版本:并发抓取,上限为 :attr:max_concurrency。
委托给 :meth:stream,核心 worker 循环只实现一份。
源代码位于: src/web_crawler/spider/spider.py
parse
¶
pause
¶
run
¶
run(
*,
max_requests: int | None = None,
state_file: str | Path | None = None,
resume: bool = False,
) -> list[Any]
同步运行 spider 并返回收集到的 item。
Parameters¶
max_requests:
本次运行发出请求数的硬上限。
state_file:
用于暂停/恢复的 JSON 文件路径。resume 为 True 且文件存在时,
队列与已见集合会被恢复。
resume:
state_file 存在时从其恢复。
源代码位于: src/web_crawler/spider/spider.py
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 | |
start_requests
¶
stream
async
¶
stream(
*,
max_requests: int | None = None,
state_file: str | Path | None = None,
resume: bool = False,
) -> AsyncIterator[Any]
异步流式产出抓取到的 item,适合长爬取与实时管道。
调度为持续流式:并发槽位空出即取队首请求派发,慢请求不会 阻塞后续请求的调度(无整批 barrier)。
用法::
async for item in spider.stream():
process(item)
与 :meth:async_run 不同,不把所有 item 缓存在内存里,而是
每抓到一条就 yield 出去(按完成顺序)。
源代码位于: src/web_crawler/spider/spider.py
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | |
web_crawler.spider.spider.Request
dataclass
¶
一个已调度的请求。
callback 是 :class:Spider 子类上的方法名(默认 "parse")。
priority 值越大越先处理。meta 会透传到 response.meta,
供回调传递状态。