Python使用BeautifulSoup提取HTML<main>标签数据问题咨询
问题解答
1. 现有代码错误点与正确提取main标签数据的方法
你的代码有3个核心错误:
- 属性匹配逻辑写反:查找s2时,你把
class属性的值传给了id参数。a-section mojo-body aok-relative是目标div的class属性,不是id,用id参数匹配必然返回None。 - 裸请求被反爬拦截:Box Office Mojo是亚马逊旗下站点,默认requests请求的UA标识为
python-requests/版本号,会被站点反爬规则识别,返回的是不完整的异常响应页,不是你在浏览器中看到的完整DOM结构,这也是你写s0.find('main')和s0.find(id='')返回结果一致的根本原因——异常页面根本没有正常的main标签结构。 - 无效的查找逻辑:
s0.find(id='')的作用是查找s0下第一个没有id属性的标签,和定位main标签没有任何关系,测试时结果重合只是异常页面结构巧合导致的。
正确提取步骤:
- 给requests添加正常浏览器的请求头,至少携带合法User-Agent,绕过基础反爬
- 标签属性匹配时,类属性传给
class_参数(因class是Python关键字,BeautifulSoup做了参数名适配) - 直接定位main标签即可,不需要逐层从外层div硬套
修正后的基础可运行代码:
import requests from bs4 import BeautifulSoup listOfFranchiseLink = "https://www.boxofficemojo.com/franchise/?ref_=bo_nb_bns_secondarytab" # 添加合法请求头模拟浏览器访问 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" } r = requests.get(listOfFranchiseLink, headers=headers) soup = BeautifulSoup(r.content, 'html.parser') # 直接定位main标签 main_content = soup.find('main') # 匹配main下对应class的内容容器 content_box = main_content.find('div', class_='a-section mojo-body aok-relative') assert main_content is not None assert content_box is not None
2. 多层嵌套标签的高效提取写法
逐层调用find的套娃写法不仅效率低、可读性差,页面前端结构稍微调整就会直接失效,标准高效的写法有两种:
- 使用CSS选择器一步定位:直接调用BeautifulSoup的
select()(匹配多个结果)或select_one()(匹配单个结果)方法,写CSS选择器路径即可一次性拿到目标节点,不需要逐层存中间变量。比如上面找内容容器的逻辑,直接写soup.select_one('main div.a-section.mojo-body.aok-relative')就能一步拿到结果,多个类名直接用点连接,不需要逐层查找。 - 批量提取场景优先就近定位:如果要提取列表/表格类的批量数据,直接找到所有目标节点的最近公共父节点,再调用
find_all()批量抓取子节点即可,不要从最外层html标签开始逐层往下数。
注意:写选择器时尽量依赖稳定的id、专属class属性定位,不要靠标签的排列位置(比如第几个div)匹配,能大幅降低页面改版导致的代码失效概率。
内容的提问来源于stack exchange,提问作者Yun
相关产品推荐
相关产品推荐

