
本教程旨在解决使用beautifulsoup进行网页抓取时遇到的常见“空列表”问题。核心在于指导用户如何通过精确的css选择器定位目标数据,避免因选择器不当导致`find()`或`find_all()`返回`none`。文章将详细解析错误原因,并提供一个优化的解决方案,通过遍历文章容器来稳定提取新闻标题和内容,确保数据抓取的准确性和可靠性。
在使用BeautifulSoup进行网页数据抓取时,一个常见的问题是最终得到一个空列表。这通常不是因为网页没有数据,而是因为我们的选择器未能准确地定位到目标元素。
以以下原始代码为例:
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'])来获取新闻标题和文章内容。然而,问题在于soup.find()方法只会返回第一个匹配的元素,如果找不到则返回None。更重要的是,这里使用的class_参数期望的是一个字符串或一个列表,但find方法返回的单个元素(如果找到)或None,当它们是None时,随后的条件if headlines and articles将评估为假,导致news_data保持为空。即使找到了单个元素,len(headlines)或len(articles)也会报错,因为None或单个Tag对象不具备len()属性。
正确的做法是使用find_all()来获取所有匹配的元素列表,但即使如此,如果选择器不够精确,也可能导致列表为空或包含非预期的元素。
网页结构复杂多变,选择器是定位元素的关键。一个好的选择器应该足够具体,能够唯一或准确地标识出目标元素。当find()或find_all()返回空结果时,通常意味着:
对于本例,问题在于news-card-title和news-right-box等类名可能并非直接对应新闻标题和内容的独立容器,或者它们被用于更复杂的布局中,导致直接查找它们无法获取到所有新闻条目。
为了解决上述问题,我们可以采用更强大的CSS选择器来精准定位数据。BeautifulSoup提供了select()和select_one()方法,它们允许我们使用CSS选择器语法来查找元素,这在处理复杂网页结构时非常有效。
核心思路是:
以下是优化后的代码示例:
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="http://schema.org/NewsArticle"] 是一种属性选择器,
# 用于匹配所有具有指定itemtype属性的元素,这通常是新闻文章的语义化标记
for article_container in soup.select('[itemtype="http://schema.org/NewsArticle"]'):
# 在每个文章容器内部,使用select_one定位标题和内容
# itemprop="headline" 和 itemprop="articleBody" 是微数据属性,
# 用于语义化地标记新闻标题和文章主体
headline_element = article_container.select_one('[itemprop="headline"]')
article_body_element = article_container.select_one('[itemprop="articleBody"]')
news_headline = headline_element.get_text(strip=True) if headline_element else None
news_article = article_body_element.get_text(strip=True) if article_body_element else None
if news_headline and news_article: # 确保提取到了有效数据
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"]')
提取子元素:article_container.select_one('[itemprop="headline"]')
获取文本内容:element.get_text(strip=True)
数据结构优化:
通过本教程,我们了解了BeautifulSoup中出现空列表的常见原因,并掌握了如何通过精确的CSS选择器和迭代父级容器的方法来解决这一问题。核心在于理解find()、find_all()、select()和select_one()的区别与适用场景,并善用get_text()来稳健地提取文本内容。掌握这些技巧将显著提升你使用BeautifulSoup进行网页抓取时的效率和成功率。
以上就是优化BeautifulSoup选择器:避免网络爬虫返回空数据的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号