使用BeautifulSoup通过href分页爬取onthisday指定日期全部历史事件
问题修复方案
你的代码存在两处核心问题:
- 下一页URL拼接错误,你获取到的
next_link['href']本身已经包含/events/前缀,重复拼接会触发404错误无法拿到后续页内容 - 仅处理了第二页内容,没有适配超过2页的场景,同时没有将后续页的事件合并到结果列表中,仅做了打印输出
修正后完整代码
from typing import List import requests as _requests import bs4 as _bs4 def _generate_url(month: str, day: int) -> str: return f'https://www.onthisday.com/events/{month}/{day}' def _get_page(url: str) -> _bs4.BeautifulSoup: # 增加请求头模拟浏览器访问,避免被反爬拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } _page = _requests.get(url, headers=headers) # 增加状态码校验,请求失败直接抛出异常 _page.raise_for_status() return _bs4.BeautifulSoup(_page.content, 'html.parser') def events_of_the_day(month: str, day: int) -> List[str]: """ Return the events of a given day """ current_url = _generate_url(month, day) raw_events = [] # 循环处理所有分页 while current_url: page = _get_page(current_url) # 追加当前页的事件到结果列表 raw_events.extend([event.text.strip() for event in page.select("li.event")]) # 查找下一页链接 next_link = page.select_one("a.pag__next") if next_link and next_link.get("href"): # 直接拼接根域名和href,避免路径重复 current_url = f"https://www.onthisday.com{next_link['href']}" else: # 没有下一页则结束循环 current_url = None return raw_events # 测试调用 if __name__ == "__main__": events = events_of_the_day("february", 5) for eve in events: print(eve)
核心改动说明
- 修复了下一页URL的拼接逻辑,直接基于站点根域名拼接href属性,避免路径重复导致的404问题
- 改用while循环迭代处理所有分页,直到没有下一页链接为止,自动适配单页、多页两种场景
- 把所有分页的事件都追加到同一个结果列表中,最终统一返回,符合函数的返回类型注解要求
- 增加了请求头模拟浏览器访问,避免被站点反爬策略拦截,同时增加了请求状态校验,便于定位请求异常问题
内容的提问来源于stack exchange,提问作者dougj
相关产品推荐
相关产品推荐

