
本文旨在解决使用beautifulsoup进行网页抓取时,因选择器不准确或数据提取方式不当导致返回空列表的常见问题。通过分析错误示例,我们将重点介绍如何利用css选择器进行更精确的元素定位,并采用迭代父元素、逐个提取子元素的高效策略,辅以`.get_text()`方法确保文本内容的正确获取,从而构建稳定可靠的网页数据抓取程序。
网页抓取中空列表问题的根源
在使用Python的requests和BeautifulSoup库进行网页数据抓取时,一个常见的困扰是程序最终输出一个空列表。这通常不是因为网络请求失败(尽管这也是一个需要检查的因素),而是因为BeautifulSoup未能根据我们提供的选择器找到目标元素。
以以下代码片段为例,它尝试从inshorts.com抓取新闻标题和内容:
import requestsfrom bs4 import BeautifulSoupurl = 'https://inshorts.com/en/read/technology'news_data = []news_category = url.split('/')[-1]headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}data = requests.get(url, headers=headers)if data.status_code == 200: soup = BeautifulSoup(data.content, 'html.parser') # 原始代码中的选择器 headlines = soup.find('div', class_=['news-card-title', 'news-right-box']) articles = soup.find('div', class_=['news-card-content', 'news-right-box']) if headlines and articles and len(headlines) == len(articles): news_articles = [ { 'news_headline': headline.find_all('span', attrs={'itemprop': 'headline'}).string, 'news_article': article.find_all('div', attrs={'itemprop': 'articleBody'}).string, 'news_category': news_category } for headline, article in zip(headlines, articles) ] news_data.extend(news_articles)print(news_data)
这段代码返回空列表的主要原因在于其选择器存在问题。soup.find(‘div’, class_=[‘news-card-title’, ‘news-right-box’])和soup.find(‘div’, class_=[‘news-card-content’, ‘news-right-box’])这两个语句很可能返回None。find()方法只返回匹配的第一个元素,并且在处理class_参数时,传入列表通常表示匹配所有这些类,而不是匹配其中任意一个。更重要的是,如果选择器不准确,find()将直接返回None,导致后续对headlines或articles进行操作时引发错误,或者在if headlines and articles条件判断时直接失败,最终导致news_data保持为空。此外,即使元素被找到,find_all(…).string也可能无法正确提取文本,因为find_all返回的是一个列表,即使只有一个元素,也需要进一步处理,且.string属性仅适用于只有一个子节点的标签。
优化选择器与数据提取策略
为了解决上述问题,我们需要采用更精确的选择器和更健壮的数据提取逻辑。关键在于:
虎课网
虎课网是超过1800万用户信赖的自学平台,拥有海量设计、绘画、摄影、办公软件、职业技能等优质的高清教程视频,用户可以根据行业和兴趣爱好,自主选择学习内容,每天免费学习一个…
62 查看详情
利用CSS选择器: Beautiful Soup支持强大的CSS选择器,通过select()和select_one()方法,我们可以编写更简洁、更准确的定位规则。定位父级容器: 优先找到包含所有目标信息的共同父级容器。这样可以确保我们处理的是一个个完整的数据单元。迭代与局部提取: 遍历每个父级容器,然后在该容器的范围内进一步提取其子元素的信息。使用.get_text(): 确保正确提取元素的文本内容,避免.string属性可能带来的问题。
改进后的抓取代码示例
以下是优化后的代码,展示了如何应用这些策略:
import requestsfrom bs4 import BeautifulSoupurl = 'https://inshorts.com/en/read/technology'news_data = []news_category = url.split('/')[-1]headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}data = requests.get(url, headers=headers)if data.status_code == 200: soup = BeautifulSoup(data.content, 'html.parser') # 使用CSS选择器定位每个新闻文章的父级容器 # 经过网页检查,发现每个新闻文章都由一个具有特定itemtype属性的div包裹 for article in soup.select('[itemtype="http://schema.org/NewsArticle"]'): # 在每个article容器内,使用select_one定位标题和文章内容 headline_element = article.select_one('[itemprop="headline"]') article_body_element = article.select_one('[itemprop="articleBody"]') # 检查元素是否存在,并使用.get_text()提取文本 news_headline = headline_element.get_text(strip=True) if headline_element else "N/A" news_article = article_body_element.get_text(strip=True) if article_body_element else "N/A" news_data.append( { 'news_headline': news_headline, 'news_article': news_article, 'news_category': news_category } )print(news_data)
代码解析:
soup.select(‘[itemtype=”http://schema.org/NewsArticle”]’): 这是核心改进。通过检查目标网页的HTML结构(通常使用浏览器开发者工具),我们发现每篇新闻文章都由一个div标签包裹,该标签具有itemtype=”http://schema.org/NewsArticle”属性。这是一个非常精确且稳定的CSS选择器,能够直接选中所有新闻文章的根容器。select()方法会返回一个匹配所有元素的列表。for article in …: 我们遍历select()返回的每个article元素,确保我们逐个处理每篇新闻。article.select_one(‘[itemprop=”headline”]’) 和 article.select_one(‘[itemprop=”articleBody”]’): 在每个article容器的内部,我们再次使用select_one()方法来定位新闻标题(itemprop=”headline”)和文章主体(itemprop=”articleBody”)。select_one()只返回第一个匹配的元素,适用于我们期望只找到一个标题或一个文章主体的情况。.get_text(strip=True): 这是提取文本内容的推荐方法。get_text()会获取元素及其所有子元素的可见文本内容,strip=True参数可以去除文本两端的空白字符,使结果更整洁。同时,我们添加了if headline_element else “N/A”这样的检查,以防某些元素确实缺失,增强代码的鲁棒性。
注意事项与最佳实践
审查HTML结构: 在编写任何选择器之前,务必使用浏览器的开发者工具(F12)仔细检查目标网页的HTML结构。理解元素的层级关系、ID、类名、属性等是编写有效选择器的基础。CSS选择器优先: 对于复杂的选择需求,CSS选择器通常比find()和find_all()的组合更强大、更简洁。它们支持ID、类名、属性、子元素、兄弟元素等多种组合方式。处理动态内容: 如果目标网站使用JavaScript动态加载内容,requests和BeautifulSoup可能无法获取到这些内容。此时,您可能需要考虑使用Selenium等工具来模拟浏览器行为。User-Agent: 在请求头中设置User-Agent是一个良好的实践,可以模拟浏览器访问,降低被网站识别为爬虫并阻止的风险。错误处理: 始终考虑网络请求失败(data.status_code != 200)和元素未找到(选择器返回None或空列表)的情况,并进行相应的错误处理或默认值设置。遵守Robots协议: 在进行网页抓取时,请务必查看网站的robots.txt文件,了解网站是否允许爬取以及允许爬取的范围。尊重网站的使用条款。
总结
当BeautifulSoup返回空列表时,通常意味着您的选择器未能准确匹配目标元素。通过采用更精确的CSS选择器(如select()和select_one()),定位包含完整数据单元的父级容器,并在其内部进行迭代和局部提取,结合使用.get_text()方法,可以显著提高网页抓取程序的稳定性和准确性。始终牢记,深入理解目标网页的HTML结构是编写高效、健壮爬虫的关键。
以上就是解决BeautifulSoup网页抓取空列表问题:优化选择器与数据提取策略的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/596572.html
微信扫一扫
支付宝扫一扫