
本文详解如何在网页中准确选择目标表格(如 wikipedia 的“results by state”表),避免误取同类型首个表格;重点讲解 `find()` 与 `find_all()` 的关键区别、文本匹配策略及健壮性优化技巧。
在使用 Beautiful Soup 进行网页表格抓取时,一个常见误区是依赖 soup.find("table", class_="wikitable sortable")——该方法仅返回第一个匹配的 要精准定位“Results by State”表格,核心思路是:先获取所有候选表格,再通过内容特征进行筛选。以下是推荐的完整实现: ? 关键优化点说明: ? 进阶提示: 若需长期维护爬虫,建议结合 select() 方法使用 CSS 选择器(如 soup.select('h2:contains("Results by state") + div + table.wikitable')),或借助 lxml 解析器提升性能与容错性。始终以页面实际 HTML 结构为准,定期验证选择器有效性。 元素,而 Wikipedia 页面中存在多个同类表格(如上方的“Joe Biden vs Donald Trump”汇总表),导致程序总是抓取错误的目标。
import requests
from bs4 import BeautifulSoup
url = 'https://en.wikipedia.org/wiki/2020_United_States_presidential_election'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
try:
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status() # 检查HTTP错误
soup = BeautifulSoup(response.text, 'html.parser')
# ✅ 使用 find_all 获取全部候选表格(而非 find)
candidate_tables = soup.find_all('table', class_='wikitable sortable')
target_table = None
for table in candidate_tables:
# ? 更可靠的匹配方式:检查 table 标题或紧邻的标题元素(h2/h3)
# 因为 table.text 可能包含大量无关文本,易误判
heading = table.find_previous(['h2', 'h3'])
if heading and 'Results by state' in heading.get_text():
target_table = table
break
if not target_table:
raise ValueError("未找到 'Results by state' 表格,请检查页面结构是否变更")
# 提取表头(th)
headers = [th.get_text(strip=True) for th in target_table.find_all('th')]
# 提取数据行(tr → td)
rows = []
for tr in target_table.find_all('tr')[1:]: # 跳过表头行
tds = tr.find_all(['td', 'th']) # 部分行可能含 th(如州名行)
row = [td.get_text(strip=True) for td in tds]
if row: # 过滤空行
rows.append(row)
print("表头:", headers)
print("前3行数据:", rows[:3])
except requests.RequestException as e:
print(f"网络请求失败: {e}")
except Exception as e:
print(f"解析异常: {e}")
的维基表格惯例。










