Python网页抓取:如何编写双重循环处理双变量URL?
问题分析与解决
你的代码存在三个核心问题导致无法获取数据:
- URL变量顺序错误:示例URL格式是
/BBSDD0002/文档编号?page=页码,但你代码里把页码和文档编号的位置写反了,生成的URL完全不符合目标地址。 - 笛卡尔积循环逻辑错误:
itertools.product会生成所有页码和文档编号的组合,这和示例中“同一页码对应一批特定文档编号”的对应关系不符,会产生大量无效请求,打乱正确的对应逻辑。 - 文档编号范围方向错误:示例里文档编号是从93976递减到39045,但你用
range(39045, 93976)生成的是递增序列,和实际目标编号方向相反。
修正方案
场景1:已知每个页码对应的文档编号范围
如果能明确每个页码对应的文档编号区间(比如page1对应9394593976,page2对应9392593930),可以直接按页码分组处理:
import requests from bs4 import BeautifulSoup # 定义每个页码对应的文档编号范围(示例) page_doc_map = { 1: range(93945, 93977), # range是左闭右开,所以结束值+1 2: range(93925, 93931), # 继续添加其他页码对应的范围 536: range(39045, 39046) } headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"} for page_num, doc_nums in page_doc_map.items(): print(f"当前处理页码: {page_num}") # 文档编号是递减的,反转range序列 for doc_num in reversed(doc_nums): url = f"https://000.com/BBSDD0002/{doc_num}?page={page_num}&" try: res = requests.get(url, headers=headers) res.raise_for_status() soup = BeautifulSoup(res.text, "lxml") list1 = soup.find_all("td", attrs={"class": "sbj"}) for li in list1: print(li.get_text()) except requests.exceptions.HTTPError as e: print(f"请求URL {url} 失败: {e}")
场景2:文档编号整体递减,每个页码对应固定数量的文档
如果文档编号从93976开始递减,每个页码对应固定数量的文档,可以先计算每个页码对应的文档编号起始和结束值:
import requests from bs4 import BeautifulSoup start_doc = 93976 end_doc = 39045 total_pages = 536 # 假设每个页码平均分配文档数(数量不均时需调整逻辑) docs_per_page = (start_doc - end_doc) // total_pages headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"} for page_num in range(1, total_pages + 1): print(f"当前处理页码: {page_num}") # 计算当前页码对应的文档编号起始值 current_start = start_doc - (page_num - 1) * docs_per_page # 最后一页处理剩余的文档 current_end = end_doc if page_num == total_pages else current_start - docs_per_page + 1 # 从current_start递减到current_end for doc_num in range(current_start, current_end - 1, -1): url = f"https://000.com/BBSDD0002/{doc_num}?page={page_num}&" try: res = requests.get(url, headers=headers) res.raise_for_status() soup = BeautifulSoup(res.text, "lxml") list1 = soup.find_all("td", attrs={"class": "sbj"}) for li in list1: print(li.get_text()) except requests.exceptions.HTTPError as e: print(f"请求URL {url} 失败: {e}")
关键修正点总结
- 确保URL中
文档编号和页码的位置与示例一致 - 不要用
product生成无意义的组合,根据实际对应关系循环 - 文档编号序列要匹配示例中的递减方向
- 添加异常处理,避免单个请求失败导致程序中断
内容的提问来源于stack exchange,提问作者Julia
相关产品推荐
相关产品推荐

