如何用BeautifulSoup爬取维基百科指定列表并转为DataFrame?
解决维基百科特定战争列表爬取并生成DataFrame的问题
核心思路
维基百科内容按标题层级结构化排布,目标列表紧接在Modern wars with fewer than 25,000 deaths by death toll二级标题之后。直接定位该标题,再抓取其后续的列表元素,就能避开无关内容。
完整代码实现
import requests from bs4 import BeautifulSoup import pandas as pd import re # 目标页面URL url = "https://en.wikipedia.org/wiki/List_of_wars_by_death_toll" # 请求页面并解析 response = requests.get(url) soup = BeautifulSoup(response.content, "html.parser") # 定位目标标题对应的span标签(维基百科标题会生成唯一id) target_title_span = soup.find("span", id="Modern_wars_with_fewer_than_25,000_deaths_by_death_toll") if not target_title_span: raise ValueError("目标标题未找到,请检查页面结构是否更新") # 获取标题的父级h2元素,再找后续的ul列表(目标数据所在) target_ul = target_title_span.parent.find_next_sibling("div").find("ul") # 初始化存储数据的列表 war_data = [] # 正则表达式匹配列表项格式:死亡人数 战争名称 (日期) pattern = re.compile(r"^([\d,]+)\s+(.*?)\s+\((.*?)\)$") # 遍历每个列表项,解析数据 for li in target_ul.find_all("li"): text = li.get_text(strip=True) match = pattern.match(text) if match: death_toll = match.group(1).replace(",", "") # 去掉逗号转成数字格式 war_name = match.group(2) date = match.group(3) war_data.append({"Death toll": death_toll, "War": war_name, "Date": date}) # 生成DataFrame df = pd.DataFrame(war_data) print(df.head())
关键步骤说明
- 精准定位目标标题:利用维基百科自动生成的标题
id直接定位,比遍历所有标题或列表高效得多,避免误抓其他内容。 - 抓取目标列表:标题的父级
<h2>之后,第一个包含列表的<div>里的<ul>就是目标数据,通过find_next_sibling()快速定位。 - 解析列表内容:用正则表达式匹配固定格式的列表项,精准拆分出死亡人数、战争名称和日期三列,避免字符串分割带来的格式误差。
内容的提问来源于stack exchange,提问作者Q.Ask
相关产品推荐
相关产品推荐

