0

0

Python中使用Beautiful Soup进行网页抓取:基础知识探究

PHPz

PHPz

发布时间:2023-09-02 10:49:02

|

1337人浏览过

|

来源于php中文网

原创

python中使用beautiful soup进行网页抓取:基础知识探究

在之前的教程中,我向您展示了如何使用 Requests 模块通过 Python 访问网页。本教程涵盖了很多主题,例如发出 GET/POST 请求以及以编程方式下载图像或 PDF 等内容。该教程缺少的一件事是如何抓取您使用请求访问的网页以提取所需信息的指南。

在本教程中,您将了解 Beautiful Soup,它是一个用于从 HTML 文件中提取数据的 Python 库。本教程的重点是学习该库的基础知识,下一个教程将介绍更高级的主题。请注意,本教程的所有示例均使用 Beautiful Soup 4。

安装

您可以使用 pip 安装 Beautiful Soup 4。包名称为 beautifulsoup4。它应该适用于 Python 2 和 Python 3。

$ pip install beautifulsoup4

如果您的系统上没有安装 pip,您可以直接下载 Beautiful Soup 4 源代码 tarball 并使用 setup.py 进行安装。

立即学习Python免费学习笔记(深入)”;

$ python setup.py install

Beautiful Soup 最初打包为 Python 2 代码。当您安装它以与 Python 3 一起使用时,它会自动更新为 Python 3 代码。除非您安装该软件包,否则代码不会被转换。以下是您可能会注意到的一些常见错误:

  • 当您在 Python 3 下运行 Python 2 版本的代码时,会出现“没有名为 HTMLParser 的模块”ImportError
  • 当您在 Python 2 下运行 Python 3 版本的代码时,会出现“没有名为 html.parser 的模块”ImportError

上述两个错误都可以通过卸载并重新安装 Beautiful Soup 来纠正。

安装解析器

在讨论 Beautiful Soup 可以使用的不同解析器之间的差异之前,让我们编写代码来创建一个 soup。

from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")

BeautifulSoup 对象可以接受两个参数。第一个参数是实际标记,第二个参数是您要使用的解析器。不同的解析器是 html.parser、lxml 和 html5lib。 lxml 解析器有两个版本:HTML 解析器和 XML 解析器。

html.parser 是一个内置解析器,它在旧版本的 Python 中工作得不太好。您可以使用以下命令安装其他解析器:

$ pip install lxml
$ pip install html5lib

lxml 解析器非常快,可用于快速解析给定的 HTML。另一方面,html5lib 解析器非常慢,但也非常宽松。以下是使用每个解析器的示例:

soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

只有当您解析无效的 HTML 时,上面示例中概述的差异才有意义。然而,网络上的大多数 HTML 都是格式错误的,了解这些差异将帮助您调试一些解析错误并决定要在项目中使用哪个解析器。一般来说,lxml 解析器是一个非常好的选择。

美丽汤中的物体

Beautiful Soup 将给定的 HTML 文档解析为 Python 对象树。您需要了解四个主要的 Python 对象:TagNavigableStringBeautifulSoupComment

Tag 对象指的是文档中的实际 XML 或 HTML 标记。您可以使用 tag.name 访问标签的名称。您还可以将标签的名称设置为其他名称。名称更改将在 Beautiful Soup 生成的标记中可见。

您可以分别使用 tag['class']tag['id'] 访问不同的属性,例如标签的类和 id。您还可以使用 tag.attrs 访问整个属性字典。您还可以添加、删除或修改标签的属性。像元素的 class 这样的属性可以采用多个值,存储为列表。

标签内的文本在 Beautiful Soup 中存储为 NavigableString。它有一些有用的方法,例如 replace_with("string") 来替换标签内的文本。您还可以使用 unicode()NavigableString 转换为 unicode 字符串。

喜鹊标书
喜鹊标书

AI智能标书制作平台,10分钟智能生成20万字投标方案,大幅提升中标率!

下载

美丽汤还允许您访问网页中的评论。这些注释存储为 Comment 对象,该对象基本上也是一个 NavigableString

您已经在上一节中了解了 BeautifulSoup 对象。它用于表示整个文档。由于它不是一个实际的对象,因此它没有任何名称或属性。

获取标题、标题和链接

您可以使用 Beautiful Soup 轻松提取页面标题和其他此类数据。让我们抓取有关 Python 的维基百科页面。首先,您必须根据请求模块教程使用以下代码获取页面标记才能访问网页。

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")

现在您已经创建了汤,您可以使用以下代码获取网页的标题:

soup.title
# Python (programming language) - Wikipedia

soup.title.name
# 'title'

soup.title.string
# 'Python (programming language) - Wikipedia'

您还可以抓取网页以获取其他信息,例如主标题或第一段、它们的类或 id 属性。

soup.h1
# 

Python (programming language)

soup.h1.string # 'Python (programming language)' soup.h1['class'] # ['firstHeading'] soup.h1['id'] # 'firstHeading' soup.h1.attrs # {'class': ['firstHeading'], 'id': 'firstHeading', 'lang': 'en'} soup.h1['class'] = 'firstHeading, mainHeading' soup.h1.string.replace_with("Python - Programming Language") del soup.h1['lang'] del soup.h1['id'] soup.h1 #

Python - Programming Language

同样,您可以使用以下代码遍历文档中的所有链接或副标题:

for sub_heading in soup.find_all('h2'):
    print(sub_heading.text)
    
# all the sub-headings like Contents, History[edit]...

处理多值和重复属性

HTML 文档中的不同元素使用各种属性来实现不同的目的。例如,您可以将 class 或 id 属性添加到样式、组或标识元素。同样,您可以使用数据属性来存储任何附加信息。并非所有属性都可以接受多个值,但有一些可以。 HTML 规范对这些情况有一套明确的规则,Beautiful Soup 试图遵循所有这些规则。但是,它还允许您指定如何处理多值属性返回的数据。该功能是在4.8版本中添加的,因此在使用之前请确保您已经安装了正确的版本。

默认情况下,像 class 这样可以有多个值的属性将返回一个列表,但像 id 这样的属性将返回单个字符串值。您可以在 BeautifulSoup 构造函数中传递名为 multi_valued_attributes 的参数,并将其值设置为 None。这将确保所有属性返回的值都是字符串。

这是一个例子:

from bs4 import BeautifulSoup

markup = '''
Recent Posts
'''

soup = BeautifulSoup(markup, 'html.parser')
print(soup.a['class'])
print(soup.a['id'])
print(soup.a['data-links'] + "\n")
''' 
Output:
['notice', 'light']
recent-posts
1 5 20
'''


soup = BeautifulSoup(markup, 'html.parser', multi_valued_attributes=None)

print(soup.a['class'])
print(soup.a['id'])
print(soup.a['data-links'] + "\n")
'''
Output:
notice light
recent-posts
1 5 20
'''

无法保证您从不同网站获得的 HTML 始终完全有效。它可能存在许多不同的问题,例如重复的属性。从版本 4.9.1 开始,Beautiful Soup 允许您通过为 on_duplicate_attribute 参数设置值来指定在这种情况下应该执行的操作。不同的解析器以不同的方式处理此问题,您将需要使用内置的 html.parser 来强制执行特定行为。

from bs4 import BeautifulSoup

markup = '''
Recent Posts
'''

soup = BeautifulSoup(markup, 'lxml')
print(soup.a['class'])
# ['notice', 'light']

soup = BeautifulSoup(markup, 'html.parser', on_duplicate_attribute='ignore')
print(soup.a['class'])
# ['notice', 'light']

soup = BeautifulSoup(markup, 'html.parser', on_duplicate_attribute='replace')
print(soup.a['class'])
# ['important', 'dark']

浏览 DOM

您可以使用常规标签名称在 DOM 树中导航。链接这些标签名称可以帮助您更深入地导航树。例如,您可以使用 soup.p.a 获取给定维基百科页面第一段中的第一个链接。第一段中的所有链接都可以使用 soup.p.find_all('a') 访问。

您还可以使用 tag.contents 以列表形式访问标记的所有子级。要获取特定索引处的子项,您可以使用 tag.contents[index]。您还可以使用 .children 属性来迭代标记的子级。

仅当您想要访问标记的直接或第一级后代时,.children.contents 才有用。要获取所有后代,您可以使用 .descendants 属性。

print(soup.p.contents)
# [Python, ' is a widely used ',.....the full list]

print(soup.p.contents[10])
# readability

for child in soup.p.children:
    print(child.name)
# b
# None
# a
# None
# a
# None
# ... and so on.

您还可以使用 .parent 属性访问元素的父元素。同样,您可以使用 .parents 属性访问元素的所有祖先。顶级 标签的父级是 BeautifulSoup 对象本身,其父级为 None。

print(soup.p.parent.name)
# div

for parent in soup.p.parents:
    print(parent.name)
# div
# div
# div
# body
# html
# [document]

您可以使用 .previous_sibling.next_sibling 属性访问元素的上一个和下一个同级元素。

要使两个元素成为兄弟元素,它们应该具有相同的父元素。这意味着元素的第一个子元素不会有前一个同级元素。类似地,元素的最后一个子元素不会有下一个同级元素。在实际的网页中,元素的上一个和下一个同级元素很可能是换行符。

您还可以使用 .previous_siblings.next_siblings 迭代元素的所有同级元素。

soup.head.next_sibling
# '\n'

soup.p.a.next_sibling
# ' for '

soup.p.a.previous_sibling
# ' is a widely used '

print(soup.p.b.previous_sibling)
# None

您可以使用 .next_element 属性转到紧随当前元素之后的元素。要访问紧邻当前元素之前的元素,请使用 .previous_element 属性。

同样,您可以分别使用 .previous_elements.next_elements 迭代当前元素之前和之后的所有元素。

仅解析文档的一部分

假设您在查找特定内容时需要处理大量数据,并且节省一些处理时间或内存对您来说很重要。在这种情况下,您可以利用 Beautiful Soup 中的 SoupStrainer 类。此类允许您仅关注特定元素,而忽略文档的其余部分。例如,您可以通过在 SoupStrainer 构造函数中传递适当的选择器,使用它来忽略网页上除图像之外的所有其他内容。

请记住,汤过滤器不能与 html5lib 解析器一起使用。但是,您可以将其与 lxml 和内置解析器一起使用。下面是一个示例,我们解析美国的维基百科页面并获取类为 thumbimage 的所有图像。

import requests
from bs4 import BeautifulSoup, SoupStrainer

req = requests.get('https://en.wikipedia.org/wiki/United_States')

thumb_images = SoupStrainer(class_="thumbimage")

soup = BeautifulSoup(req.text, "lxml", parse_only=thumb_images)

for image in soup.find_all("img"):
    print(image['src'])
'''
Output:
//upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Mesa_Verde_National_Park_-_Cliff_Palace.jpg/220px-Mesa_Verde_National_Park_-_Cliff_Palace.jpg
//upload.wikimedia.org/wikipedia/commons/thumb/3/38/Map_of_territorial_growth_1775.svg/260px-Map_of_territorial_growth_1775.svg.png
//upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Declaration_of_Independence_%281819%29%2C_by_John_Trumbull.jpg/220px-Declaration_of_Independence_%281819%29%2C_by_John_Trumbull.jpg
//upload.wikimedia.org/wikipedia/commons/thumb/9/94/U.S._Territorial_Acquisitions.png/310px-U.S._Territorial_Acquisitions.png
...and many more images
'''

您应该注意,我使用 class_ 而不是 class 来获取这些元素,因为 class 是 Python 中的保留关键字。

最终想法

完成本教程后,您现在应该能够很好地理解不同 HTML 解析器之间的主要差异。您现在还应该能够浏览网页并提取重要数据。当您想要分析给定网站上的所有标题或链接时,这会很有帮助。

在本系列的下一部分中,您将学习如何使用 Beautiful Soup 库来搜索和修改 DOM。

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

760

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

639

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

762

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

618

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1265

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

709

2023.08.11

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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