url模板应基于真实结构化字段(如slug、code)动态生成,避免硬编码id;统一分页参数命名,用urljoin拼接;设层级深度上限与白名单终止条件;并发时确保参数快照独立;延迟与ua轮换应在请求层而非url模板中实现。

URL模板怎么写才不会漏页或重复
多级分类爬取的核心不是发多少请求,而是URL生成逻辑是否覆盖全且无歧义。常见错误是把分类ID硬编码进字符串,结果遇到ID不连续、跳变或带前缀(如 cat_102)就断链。
正确做法是先抓取一级分类列表,从中提取真实URL或结构化字段(如 category_id、slug),再用它们拼接二级模板。例如某电商站一级返回:{"id": "shoes", "name": "鞋类"},二级页实际是 https://site.com/c/<id>/page-<page_num></page_num></id>,而非 /category/123?page=2。
- 避免用数字序号当分类依据,优先用API返回的
slug或code - 分页参数统一用
page或offset,别混用start、limit等不同命名 - 对URL做
urllib.parse.urljoin()拼接,别直接字符串 +,否则相对路径会出错
如何控制层级深度并防止无限递归
“多级”不等于“无限深”。实际中三级已覆盖95%场景,强行追到四级往往拿到的是空页或反爬页。关键在定义清晰的终止条件,而不是靠 try-except 吞异常硬扛。
以 requests + BeautifulSoup 为例,建议在请求前就判断当前层级是否该停:
- 层级计数器达到预设值(如
max_depth=3)立即 return - 解析发现下级链接为空、或全是外链(
href以http开头但域名不匹配)则停止递进 - 对疑似“详情页”的URL加白名单规则,例如含
/item/、/p/、-detail就不再向下提取分类链接
别依赖响应状态码判断——很多站对无效分类返回 200 + 空内容,得看实际 HTML 结构。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
并发请求下如何保证URL模板参数不串
用 asyncio 或 threading 并发时,如果所有任务共用一个 URL 模板字符串并动态替换,极易因变量作用域混乱导致 page=1 的请求发出 page=5 的 URL。
根本解法是:每个请求任务必须持有完整、不可变的参数快照。
- 用
f"https://x.com/{cat_slug}/page-{page_num}"替代url_template.format(...)—— 前者每次计算,后者可能被闭包捕获旧值 - 若用
concurrent.futures.ThreadPoolExecutor,确保传入函数的参数是具体值,而非外部循环变量(常见坑:for p in pages: executor.submit(task, p)中p最终全为最后一个值) - 对异步任务,用
asyncio.create_task(crawl_page(cat_slug, page_num))显式传参,别在协程内读外部变量
反爬压力下URL模板要不要加随机延迟或UA轮换
要,但不是加在URL构建环节,而是加在请求发起前。URL模板本身是纯逻辑,掺杂延迟或UA会污染可复现性,调试时难定位是模板错还是请求策略错。
真正该干预的位置是请求封装层:
- 延迟放在
session.get(url, ...)调用前,用time.sleep(random.uniform(0.5, 2.0)) - UA轮换绑定到
session.headers,每次请求前重置,而不是拼在URL里 - 更稳妥的做法是用
fake_useragent动态获取 UA,并配合requests.adapters.HTTPAdapter控制重试和连接池
URL模板只管“我要去哪里”,不该承担“我怎么去”的职责。混淆这两者,后期加代理、Cookie池、Referer 链路时会越改越乱。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










