解决BeautifulSoup网页抓取空列表问题:优化选择器与数据提取策略

聖光之護
发布: 2025-10-14 09:40:23
原创
349人浏览过

解决BeautifulSoup网页抓取空列表问题:优化选择器与数据提取策略

本文旨在解决使用beautifulsoup进行网页抓取时,因选择器不准确或数据提取方式不当导致返回空列表的常见问题。通过分析错误示例,我们将重点介绍如何利用css选择器进行更精确的元素定位,并采用迭代父元素、逐个提取子元素的高效策略,辅以`.get_text()`方法确保文本内容的正确获取,从而构建稳定可靠的网页数据抓取程序。

网页抓取中空列表问题的根源

在使用Python的requests和BeautifulSoup库进行网页数据抓取时,一个常见的困扰是程序最终输出一个空列表。这通常不是因为网络请求失败(尽管这也是一个需要检查的因素),而是因为BeautifulSoup未能根据我们提供的选择器找到目标元素。

以以下代码片段为例,它尝试从inshorts.com抓取新闻标题和内容:

import requests
from bs4 import BeautifulSoup

url = '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
查看详情 虎课网
  1. 利用CSS选择器: Beautiful Soup支持强大的CSS选择器,通过select()和select_one()方法,我们可以编写更简洁、更准确的定位规则。
  2. 定位父级容器: 优先找到包含所有目标信息的共同父级容器。这样可以确保我们处理的是一个个完整的数据单元。
  3. 迭代与局部提取: 遍历每个父级容器,然后在该容器的范围内进一步提取其子元素的信息。
  4. 使用.get_text(): 确保正确提取元素的文本内容,避免.string属性可能带来的问题。

改进后的抓取代码示例

以下是优化后的代码,展示了如何应用这些策略:

import requests
from bs4 import BeautifulSoup

url = '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)
登录后复制

代码解析:

  1. soup.select('[itemtype="http://schema.org/NewsArticle"]'): 这是核心改进。通过检查目标网页的HTML结构(通常使用浏览器开发者工具),我们发现每篇新闻文章都由一个div标签包裹,该标签具有itemtype="http://schema.org/NewsArticle"属性。这是一个非常精确且稳定的CSS选择器,能够直接选中所有新闻文章的根容器。select()方法会返回一个匹配所有元素的列表。
  2. for article in ...: 我们遍历select()返回的每个article元素,确保我们逐个处理每篇新闻。
  3. article.select_one('[itemprop="headline"]') 和 article.select_one('[itemprop="articleBody"]'): 在每个article容器的内部,我们再次使用select_one()方法来定位新闻标题(itemprop="headline")和文章主体(itemprop="articleBody")。select_one()只返回第一个匹配的元素,适用于我们期望只找到一个标题或一个文章主体的情况。
  4. .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网页抓取空列表问题:优化选择器与数据提取策略的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号