如何通过Python3使用请求和BeautifulSoup来处理Web数据

来自菜鸟教程
跳转至:导航、​搜索

介绍

网络为我们提供的数据比我们任何人都可以阅读和理解的多,因此我们经常希望以编程方式处理这些信息以理解它。 有时,这些数据是由网站创建者通过 .csv 或逗号分隔值文件,或通过 API(应用程序编程接口)提供给我们的。 其他时候,我们需要自己从网络上收集文本。

本教程将介绍如何使用 RequestsBeautiful Soup Python 包以利用网页中的数据。 Requests 模块允许您将 Python 程序与 Web 服务集成,而 Beautiful Soup 模块旨在使屏幕抓取快速完成。 使用 Python 交互式控制台和这两个库,我们将了解如何收集网页并使用那里可用的文本信息。

先决条件

要完成本教程,您需要一个 Python 3 的开发环境。 您可以按照 如何为 Python 3如何安装 Python 3 并在Ubuntu 20.04 Server 来配置你需要的一切。

此外,您应该熟悉:

设置好开发环境并记住这些 Python 编程概念后,让我们开始使用 Requests 和 Beautiful Soup。

安装请求

让我们从激活我们的 Python 3 编程环境开始。 确保您位于环境所在的目录中,然后运行以下命令:

. my_env/bin/activate

为了处理网页,我们需要请求页面。 Requests 库允许您以人类可读的方式在 Python 程序中使用 HTTP。

激活我们的编程环境后,我们将使用 pip 安装 Requests:

pip install requests

在安装 Requests 库时,您将收到以下输出:

OutputCollecting requests
  Downloading requests-2.26.0-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 3.1MB/s 
...
Installing collected packages: chardet, urllib3, certifi, idna, requests
Successfully installed certifi-2017.4.17 chardet-3.0.4 idna-2.5 requests-2.26.0 urllib3-1.21.1

如果之前安装了 Requests,您会从终端窗口收到类似于以下内容的反馈:

OutputRequirement already satisfied
...

将 Requests 安装到我们的编程环境中后,我们可以继续安装下一个模块。

安装美丽的汤

就像我们对 Requests 所做的那样,我们将使用 pip 安装 Beautiful Soup。 可以使用以下命令安装 Beautiful Soup 4 的当前版本:

pip install beautifulsoup4

运行此命令后,您应该会看到类似于以下内容的输出:

OutputCollecting beautifulsoup4
  Downloading beautifulsoup4-4.10.0-py3-none-any.whl (97 kB)
     |████████████████████████████████| 97 kB 6.8 MB/s
Collecting soupsieve>1.2
  Downloading soupsieve-2.3.1-py3-none-any.whl (37 kB)
Installing collected packages: soupsieve, beautifulsoup4
Successfully installed beautifulsoup4-4.10.0 soupsieve-2.3.1

现在都安装了 Beautiful Soup 和 Requests,我们可以继续了解如何使用库来抓取网站。

收集带有请求的网页

现在安装我们将使用的两个 Python 库后,我们可以熟悉逐步浏览基本网页。

让我们首先进入 Python 交互式控制台

python

从这里,我们将导入 Requests 模块,以便我们可以收集示例网页:

import requests

我们将示例网页的 URL(如下),mockturtle.html 分配给 变量 url

url = 'https://assets.digitalocean.com/articles/eng_python/beautiful-soup/mockturtle.html'

接下来,我们可以使用 request.get() 方法 将该页面的请求结果分配给变量 page。 我们将页面的 URL(分配给 url 变量)传递给该方法。

page = requests.get(url)

变量 page 被分配了一个 Response 对象:

>>> page
<Response [200]>
>>> 

上面的 Response 对象告诉我们方括号中的 status_code 属性(在本例中为 200)。 可以显式调用此属性:

>>> page.status_code
200
>>> 

200的返回码告诉我们页面下载成功。 以数字2开头的代码一般表示成功,而以数字45开头的代码则表示发生了错误。 您可以从 W3C 的状态代码定义 中了解更多关于 HTTP 状态代码的信息。

为了使用 Web 数据,我们需要访问基于文本的 Web 文件内容。 我们可以使用 page.text (或者 page.content 如果我们想以字节为单位访问响应)来读取服务器响应的内容。

page.text

一旦我们按下 ENTER,我们将收到以下输出:

Output'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n    
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n\n<html lang="en-US" 
xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n<head>\n  <meta 
http-equiv="content-type" content="text/html; charset=us-ascii" />\n\n  <title>Turtle 
Soup</title>\n</head>\n\n<body>\n  <h1>Turtle Soup</h1>\n\n  <p class="verse" 
id="first">Beautiful Soup, so rich and green,<br />\n  Waiting in a hot tureen!<br />\n  Who for 
such dainties would not stoop?<br />\n  Soup of the evening, beautiful Soup!<br />\n  Soup of 
the evening, beautiful Soup!<br /></p>\n\n  <p class="chorus" id="second">Beau--ootiful 
Soo--oop!<br />\n  Beau--ootiful Soo--oop!<br />\n  Soo--oop of the e--e--evening,<br />\n  
Beautiful, beautiful Soup!<br /></p>\n\n  <p class="verse" id="third">Beautiful Soup! Who cares 
for fish,<br />\n  Game or any other dish?<br />\n  Who would not give all else for two<br />\n  
Pennyworth only of Beautiful Soup?<br />\n  Pennyworth only of beautiful Soup?<br /></p>\n\n  
<p class="chorus" id="fourth">Beau--ootiful Soo--oop!<br />\n  Beau--ootiful Soo--oop!<br />\n  
Soo--oop of the e--e--evening,<br />\n  Beautiful, beauti--FUL SOUP!<br 
/></p>\n</body>\n</html>\n'
>>> 

在这里,我们看到页面的全文已打印出来,其中包含所有 HTML 标记。 但是,由于间距不大,因此难以阅读。

在下一节中,我们可以利用 Beautiful Soup 模块以更人性化的方式处理这些文本数据。

用漂亮的汤浏览页面

Beautiful Soup 库从已解析的 HTML 和 XML 文档(包括具有非封闭标签或 tag soup 和其他格式错误的标记的文档)创建解析树。 此功能将使网页文本比我们从请求模块中看到的更具可读性。

首先,我们将 Beautiful Soup 导入 Python 控制台:

from bs4 import BeautifulSoup

接下来,我们将通过模块运行 page.text 文档,从而为我们提供一个 BeautifulSoup 对象——也就是说,我们将通过运行 Python 内置html.parser 在 HTML 上。 构造的对象将 mockturtle.html 文档表示为嵌套数据结构。 这分配给变量 soup

soup = BeautifulSoup(page.text, 'html.parser')

为了在终端上显示页面的内容,我们可以使用 prettify() 方法打印它,以便将 Beautiful Soup 解析树转换为格式良好的 Unicode 字符串。

print(soup.prettify())

这将在自己的行上呈现每个 HTML 标记:

Output<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
  <title>
   Turtle Soup
  </title>
 </head>
 <body>
  <h1>
   Turtle Soup
  </h1>
  <p class="verse" id="first">
   Beautiful Soup, so rich and green,
   <br/>
   Waiting in a hot tureen!
   <br/>
   Who for such dainties would not stoop?
   <br/>
   Soup of the evening, beautiful Soup!
 ...
</html>

在上面的输出中,我们可以看到每行有一个标签,而且标签是嵌套的,因为 Beautiful Soup 使用了树模式。

查找标签的实例

我们可以使用 Beautiful Soup 的 find_all 方法从页面中提取单个标签。 这将返回文档中给定标签的所有实例。

soup.find_all('p')

在我们的对象上运行该方法会返回歌曲的全文以及相关的 <p> 标签和包含在该请求标签中的任何标签,其中包括换行符标签 <br/>

Output[<p class="verse" id="first">Beautiful Soup, so rich and green,<br/>
  Waiting in a hot tureen!<br/>
  Who for such dainties would not stoop?<br/>
  Soup of the evening, beautiful Soup!<br/>
  Soup of the evening, beautiful Soup!<br/></p>, <p class="chorus" id="second">Beau--ootiful Soo--oop!<br/>
...
  Beau--ootiful Soo--oop!<br/>
  Soo--oop of the e--e--evening,<br/>
  Beautiful, beauti--FUL SOUP!<br/></p>]

您会在上面的输出中注意到数据包含在方括号 [ ] 中。 这意味着它是 Python 列表数据类型

因为它是一个列表,所以我们可以调用其中的特定项目(例如,第三个 <p> 元素),并使用 get_text() 方法从该标签中提取所有文本:

soup.find_all('p')[2].get_text()

在这种情况下,我们收到的输出将是第三个 <p> 元素中的内容:

Output'Beautiful Soup! Who cares for fish,\n  Game or any other dish?\n  Who would not give all else for two\n  Pennyworth only of Beautiful Soup?\n  Pennyworth only of beautiful Soup?'

请注意,\n 换行符也显示在上面返回的字符串中。

按类别和 ID 查找标签

在使用 Beautiful Soup 处理 Web 数据时,参考 CSS 选择器(如 class 和 ID)的 HTML 元素可能会有所帮助。 我们可以通过使用 find_all() 方法并将类和 ID 字符串作为参数传递来定位特定的类和 ID。

首先,让我们找到类 chorus 的所有实例。 在 Beautiful Soup 中,我们将类的字符串分配给关键字参数 class_

soup.find_all(class_='chorus')

当我们运行上述行时,我们将收到以下列表作为输出:

Output[<p class="chorus" id="second">Beau--ootiful Soo--oop!<br/>
  Beau--ootiful Soo--oop!<br/>
  Soo--oop of the e--e--evening,<br/>
  Beautiful, beautiful Soup!<br/></p>, <p class="chorus" id="fourth">Beau--ootiful Soo--oop!<br/>
  Beau--ootiful Soo--oop!<br/>
  Soo--oop of the e--e--evening,<br/>
  Beautiful, beauti--FUL SOUP!<br/></p>]

两个带有 chorus 类的 <p> 标记部分被打印到终端。

我们还可以指定只在 <p> 标签内搜索类 chorus,以防它用于多个标签:

soup.find_all('p', class_='chorus')

运行上面的行将产生与以前相同的输出。

我们还可以使用 Beautiful Soup 来定位与 HTML 标签关联的 ID。 在这种情况下,我们将字符串 'third' 分配给关键字参数 id

soup.find_all(id='third')

一旦我们运行上面的行,我们将收到以下输出:

Output[<p class="verse" id="third">Beautiful Soup! Who cares for fish,<br/>
  Game or any other dish?<br/>
  Who would not give all else for two<br/>
  Pennyworth only of Beautiful Soup?<br/>
  Pennyworth only of beautiful Soup?<br/></p>]

与 ID 为 third<p> 标签关联的文本与相关标签一起打印到终端。

结论

本教程将引导您使用 Python 中的 Requests 模块检索网页,并对该网页的文本数据进行一些初步抓取,以便了解 Beautiful Soup。

从这里,您可以继续创建一个网络抓取程序,该程序将按照教程 如何使用 Beautiful Soup 和 Python 3 从网络收集的数据创建一个 CSV 文件。