如何使用Python爬取维基百科指定子板块下的链接
精准爬取维基百科指定子板块链接实现方案
核心问题原因
之前用BeautifulSoup爬取冗余过多,本质是没有对目标板块做DOM边界截断,直接在全页面范围匹配链接标签,自然会拿到大量无关内容。维基百科的页面结构里,板块内容不是嵌套在标题标签内部,而是以同级节点的形式排列在标题标签之后,直到下一个同层级标题出现为止,顺着这个结构做范围限定就能完全避免冗余。
实现步骤
- 锚定目标板块起点:找到id为
By_genre的span标签(维基百科每个板块标题都会对应一个带唯一id的span锚点),获取它的父级标题节点作为遍历起点 - 做边界截断:从起点开始向后遍历所有同级DOM节点,一旦遇到下一个h2级别的标题(即和"By genre"同级的其他板块标题)就立刻终止遍历,把爬取范围严格锁在目标板块内
- 分组提取内容:遍历范围内的节点时,遇到h3标签就记录为当前二级分类标题(比如Action、Sports等),遇到列表标签就提取内部所有有效链接,归到当前二级分类下
可运行代码
先安装依赖:pip install requests beautifulsoup4
import requests from bs4 import BeautifulSoup # 目标页面地址 target_url = "https://en.wikipedia.org/wiki/Lists_of_video_games" # 加请求头避免被反爬拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" } response = requests.get(target_url, headers=headers) soup = BeautifulSoup(response.text, "html.parser") # 定位By genre板块的起始标题节点 section_start = soup.find("span", id="By_genre").parent current_node = section_start.next_sibling genre_result = {} current_sub_category = None # 向后遍历节点,严格控制爬取范围 while current_node: # 跳过无意义的空白文本节点 if not getattr(current_node, "name", None): current_node = current_node.next_sibling continue # 遇到h2标签说明抵达下一个同级板块,直接终止遍历 if current_node.name == "h2": break # 遇到h3标签,更新当前所属二级分类 if current_node.name == "h3": sub_cat_name = current_node.get_text(strip=True).replace("[edit]", "") current_sub_category = sub_cat_name genre_result[current_sub_category] = [] # 遇到列表标签,提取当前分类下的有效链接 elif current_node.name in ["ul", "ol"] and current_sub_category: for a_tag in current_node.find_all("a", href=True): href = a_tag["href"] # 过滤编辑链接、页内锚点等无效链接 if href.startswith("/wiki/") and "action=edit" not in href: genre_result[current_sub_category].append({ "link_text": a_tag.get_text(strip=True), "url": f"https://en.wikipedia.org{href}" }) current_node = current_node.next_sibling # 输出测试 for category, link_list in genre_result.items(): print(f"\n--- {category} ---") for link in link_list: print(f"{link['link_text']}: {link['url']}")
适配说明
- 这套边界截断逻辑可以直接复用在其他维基百科页面的板块爬取需求上,只需要把
find("span", id="By_genre")里的id替换成目标板块对应的id即可(板块标题里的空格替换为下划线就是对应id值) - 代码默认过滤了编辑链接、锚点链接,如果需要保留其他类型链接可以自行调整过滤规则
内容的提问来源于stack exchange,提问作者Mohamed Gamal Hamed
相关产品推荐
相关产品推荐

