
本文详解如何用 beautifulsoup 定位 HTML 中的 列表,逐项解析每个 子元素,并安全提取标题、链接、描述和时间戳等字段,生成结构化字典列表。
本文详解如何用 beautifulsoup 定位 html 中的 `
- ` 列表,逐项解析每个 `
- ` 子元素,并安全提取标题、链接、描述和时间戳等字段,生成结构化字典列表。
在网页爬虫开发中,搜索结果页常以有序列表(
- )组织多个条目,每个
- 包含标题(
)、链接()、摘要(
)及时间戳(如带 data-timestamp 属性的 )。仅定位到
- 远不足够——关键在于精准遍历
- 并稳健提取嵌套字段 。
以下为完整、健壮的实现方案:
from bs4 import BeautifulSoup # 假设 session 已初始化,url 为目标搜索结果页 result = session.get(url) soup = BeautifulSoup(result.text, 'html.parser') # ✅ 正确做法:先定位唯一 ol(用 find 而非 find_all),再遍历其所有 li search_results = soup.find('ol', class_='searchResults') if not search_results: raise ValueError("未找到 class='searchResults' 的有序列表") parsed_items = [] for li in search_results.find_all('li'): # 使用条件表达式 + .get() / .text 防止 AttributeError title_elem = li.find('h4') link_elem = li.find('a') desc_elem = li.find('p') time_elem = li.find('span', class_='lastSeen') # 推荐用 class_=... 更简洁 item = { 'title': title_elem.get_text(strip=True) if title_elem else '', 'link': link_elem.get('href') if link_elem else '', 'description': desc_elem.get_text(strip=True) if desc_elem else '', 'timestamp': time_elem.get('data-timestamp') if time_elem else '' } parsed_items.append(item) # 输出示例(前两条) for i, item in enumerate(parsed_items[:2], 1): print(f"第{i}条:", item)? 关键要点说明:
- find() vs find_all():
- 在页面中通常唯一,应使用 soup.find(…) 获取单个对象;而
- 有多个,才用 find_all(‘li’)。
- 防御性解析:每个 .find() 后都检查是否为 None,避免 AttributeError;.get_text(strip=True) 比 .text 更安全(自动处理空白与 None)。
- 属性选择优化:find(‘span’, class_=’lastSeen’) 比 find(‘span’, {‘class’: ‘lastSeen’}) 更符合 BeautifulSoup 最佳实践。
- 结构化存储:parsed_items 是标准 Python 字典列表,可直接转为 pandas.DataFrame、json 文件或存入数据库。
? 进阶建议:若需高可靠性,可封装为函数并加入日志与重试机制;对动态渲染页面,考虑切换至 Selenium 或 Playwright 配合 BeautifulSoup 解析 dom 快照。始终遵守 robots.txt 并设置合理请求间隔,尊重网站爬虫协议。
- 包含标题(