使用 Python requests 和 Beautiful Soup 分析网页

按照本 Python 教程轻松提取网页信息。
5 位读者喜欢这篇文章。
Python programming language logo with question marks

Opensource.com

浏览网页可能占据你一天的大部分时间。 但这是一个非常手动的过程,不是吗? 你必须打开浏览器。 前往网站。 单击按钮,移动鼠标。 这很费劲。 通过代码与 Internet 交互不是更好吗?

你可以借助 Python 模块 requests 从 Internet 获取数据

import requests

DATA = "https://open-source.net.cn/article/22/5/document-source-code-doxygen-linux"
PAGE = requests.get(DATA)

print(PAGE.text)

在此代码示例中,你首先导入模块 requests。 然后,你创建两个变量:一个名为 DATA,用于保存你要下载的 URL。 在此代码的后续版本中,你每次运行应用程序时都可以提供不同的 URL。 但是现在,最简单的方法是为演示目的“硬编码”一个测试 URL。

另一个变量是 PAGE,你将其设置为 requests.get 函数读取存储在 DATA 中的 URL 时的响应 requests 模块及其 .get 函数预先编程为“读取”Internet 地址(URL)、访问 Internet 并下载位于该地址的内容。

你无需自己弄清楚很多步骤,这正是 Python 模块存在的原因。 最后,你告诉 Python print requests.get 存储在 PAGE 变量的 .text 字段中的所有内容。

Beautiful Soup

如果运行上面的示例代码,你将会看到示例 URL 的内容不加选择地转储到你的终端中。 它这样做是因为你的代码对 requests 收集的数据所做的唯一事情就是打印它。 解析文本更有趣。

Python 可以使用其最基本的功能“读取”文本,但解析文本允许你搜索模式、特定单词、HTML 标签等等。 你可以自己解析 requests 返回的文本,但使用专门的模块会容易得多。 对于 HTML 和 XML,可以使用 Beautiful Soup 库。

此代码完成相同的事情,但它使用 Beautiful Soup 来解析下载的文本。 因为 Beautiful Soup 识别 HTML 实体,所以你可以使用它的一些内置功能使输出更容易让人眼解析。

例如,与其在程序的末尾打印原始文本,不如通过 Beautiful Soup 的 .prettify 函数运行文本

from bs4 import BeautifulSoup
import requests

PAGE = requests.get("https://open-source.net.cn/article/22/5/document-source-code-doxygen-linux")
SOUP = BeautifulSoup(PAGE.text, 'html.parser')

# Run the script
if __name__ == '__main__':
    # do a thing here
    print(SOUP.prettify())

此版本的程序的输出确保每个开头的 HTML 标签都从它自己的行开始,并带有缩进以帮助演示哪个标签是另一个标签的父级。 Beautiful Soup 在很多方面都知道 HTML 标签,而不仅仅是如何打印它。

你可以单独挑出一种特定类型的标签,而不是打印整个页面。 例如,尝试将打印选择器从 print(SOUP.prettify() 更改为

  print(SOUP.p)

这只会打印一个 <p> 标签。 具体来说,它只会打印遇到的第一个 <p> 标签。 要打印所有 <p> 标签,你需要一个循环。

循环

创建一个 for 循环,以使用 Beautiful Soup 的 find_all 函数循环遍历 SOUP 变量中包含的整个网页。 想要将你的循环用于除 <p> 标签之外的其他标签并非不合理,因此请将其构建为自定义函数,由 Python 中的 def 关键字(对于“define”)指定。

def loopit():
    for TAG in SOUP.find_all('p'):
        print(TAG)

临时变量 TAG 是任意的。 你可以使用任何术语,例如 ITEMi 或任何你想要的东西。 每次循环运行时,TAG 都包含 find_all 函数的搜索结果。 在此代码中,正在搜索 <p> 标签。

除非明确调用函数,否则函数不会运行。 你可以在代码末尾调用你的函数

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    # do a thing here
    loopit()

运行你的代码以查看所有 <p> 标签以及每个标签的内容。

仅获取内容

你可以通过指定你只想要“字符串”(编程术语中的“单词”)来排除打印标签。

def loopit():
    for TAG in SOUP.find_all('p'):
        print(TAG.string)

当然,一旦你有了网页的文本,你就可以使用标准的 Python 字符串库进一步解析它。 例如,你可以使用 lensplit 来获取单词计数

def loopit():
    for TAG in SOUP.find_all('p'):
        if TAG.string is not None:
            print(len(TAG.string.split()))

这会打印每个段落元素中的字符串数量,省略那些没有任何字符串的段落。 要获得总数,请使用变量和一些基本数学运算

def loopit():
    NUM = 0
    for TAG in SOUP.find_all('p'):
        if TAG.string is not None:
            NUM = NUM + len(TAG.string.split())
    print("Grand total is ", NUM)

Python 作业

你可以使用 Beautiful Soup 和 Python 提取更多信息。 以下是有关如何改进你的应用程序的一些想法

  • 接受输入,以便你可以在启动应用程序时指定要下载和分析的 URL。
  • 计算页面上的图像数量(<img> 标签)。
  • 计算另一个标签内的图像数量(<img> 标签)(例如,仅出现在 <main> div 中的图像,或仅出现在 </p> 标签之后的图像)。
下一步阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。 他曾在电影和计算行业工作过,而且经常同时从事这两项工作。

2 条评论

当我使用 BS4 进行抓取时,我无法将其与我的 Google API 集成,如何解决此问题? 我对相关建议持开放态度。 谢谢

prettify 的功能是什么?

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.