用漂亮的汤在Python中抓取网页:基础知识

在上一教程中,我向您展示了如何使用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 setup.py install

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

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

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

安装解析器

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

from bs4 import BeautifulSoup

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "html.parser")

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

html.parser是内置的解析器,在旧版本的Python中效果不佳。 您可以使用以下命令安装其他解析器:

$ pip install lxml
$ pip install html5lib

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

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "html.parser")
print(soup)
# <html><p>This is <b>invalid HTML</b></p></html>

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "lxml")
print(soup)
# <html><body><p>This is <b>invalid HTML</b></p></body></html>

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "xml")
print(soup)
# <?xml version="1.0" encoding="utf-8"?>
# <html><p>This is <b>invalid HTML</b></p></html>

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "html5lib")
print(soup)
# <html><head></head><body><p>This is <b>invalid HTML</b></p></body></html>

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

美丽汤中的对象

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

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

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

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

Beautiful Soup还可以让您访问网页中的评论。 这些注释存储为Comment对象,该对象基本上也是NavigableString

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

获取标题,标题和链接

您可以使用Beautiful Soup非常轻松地提取页面标题和其他此类数据。 让我们抓取有关PythonWikipedia页面 。 首先,您将必须使用以下基于请求模块教程的代码来获取页面的标记, 以访问网页

import requests
from bs4 import BeautifulSoup

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

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

soup.title
# <title>Python (programming language) - Wikipedia</title>

soup.title.name
# 'title'

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

您也可以抓取网页以获得其他信息,例如主标题或第一段,其类或id属性。

soup.h1
# <h1 class="firstHeading" id="firstHeading" lang="en">Python (programming language)</h1>

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
# <h1 class="firstHeading, mainHeading">Python - Programming Language</h1>

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

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

导航DOM

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

您还可以使用tag.contents将标签的所有子级作为列表tag.contents 。 要使子级处于特定索引,可以使用tag.contents[index] 。 您还可以使用.children属性来遍历标签的子级。

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

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

print(soup.p.contents[10])
# <a href="/wiki/Readability" title="Readability">readability</a>

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

您还可以使用.parent属性访问元素的父.parent 。 同样,您可以使用.parents属性访问元素的所有祖先。 顶级<html>标记的父级是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遍历元素的所有同级.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属性.next_element当前元素之后的元素。 要访问紧接当前元素的元素,请使用.previous_element属性。

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

最后的想法

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

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

翻译自: https://code.tutsplus.com/tutorials/scraping-webpages-in-python-with-beautiful-soup-the-basics--cms-28211

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值