Beautiful Soup 是一个广泛使用的 Python 库,在数据提取方面发挥着重要作用。它为解析 HTML 和 XML 文档提供了强大的工具,使从网页中轻松提取有价值的数据成为可能。该库简化了处理互联网上非结构化内容的复杂过程,使您可以将原始网页数据转换为结构化的可用格式。
HTML 文档解析在信息世界中起着举足轻重的作用。HTML 数据可进一步用于数据整合、分析和自动化,涵盖从商业智能到研究等各个方面。网络是一个庞大的地方,充满了有价值的信息;因此,在本指南中,我们将使用各种工具和脚本来探索浩瀚的海洋,并教它们带回所有数据。
什么是数据解析?
数据解析是分析数据以提取有意义的信息或将其转换为更有结构的格式的过程。说到网页内容,这些数据通常以 HTML 文档的形式出现。虽然它们是网站的组成部分,但我们只关心其中存储的信息。通过数据解析,我们分析这些文件以查找数据、清理数据,然后将其转换为 CSV 或 JSON 文件等易于阅读的格式,以便进一步分析和使用。
解析数据是收集数据过程的重要组成部分。清理后的数据可用于分析和统计,为您的个人或业务需求提供有价值的见解。数据解析的另一个好处是,它可以将不同来源的数据结合起来,让您创建新的、多样化的数据集。例如,从电子商务网站收集数据时,它可以查找、连接和计算竞争对手产品的平均价格。这样的知识可以帮助你对网站上的产品定价做出明智的决定,并在市场上保持领先地位。
更酷的是,数据的收集和处理可以通过直观的功能实现完全自动化。它减少了手动输入和处理数据的需要,节省了时间并降低了人为错误的风险。这意味着你有一个小精灵在观察你的竞争对手,分析他们,并提供有价值的见解,一年 365 天,一天 24 小时,没有咖啡休息时间或延长假期。在熟睡中击败竞争对手,你不觉得很灵活吗?
什么是Beautiful Soup?
如果你已经迷上了数据解析的概念,你可能会尝试打开 HTML 文档,阅读其中的信息,感觉就像在尝试破译古老的象形文字。你也可能把它看成是一碗汤–把各种配料放在一起,切片、煮沸、烹饪。它们一起构成了美味的一餐,但如果你试图挑出每一片胡萝卜(不管出于什么原因),你可能就会意识到这是一项多么复杂的工作。
Beautiful Soup 来拯救你了,它能让你的汤更美。它是一个 Python 库,通常用于刮取和解析 HTML 和 XML 文档,并提供导航和搜索其中内容的工具。Beautiful Soup 能让开发人员更轻松地以更有条理、更易读的格式提取和处理数据。
安装和设置
Beautiful Soup 的安装简单快捷。首先,您需要在计算机或虚拟环境中安装 Python,并使用 pippacket 管理器安装 Python 库。从 3.4+ 版本开始,默认安装 pip。您可以在终端运行此命令来检查是否已安装:
py -m pip –version
然后,只需运行以下命令即可安装 Beautiful Soup:
pip install beautifulsoup4
就是这样!安装 Python 软件包只需几秒钟,您就可以在网络搜索项目中使用它了。
Beuatiful Soup 基础知识
首先,您需要测试一切工作是否正常。编写一段简单的代码,从以下 HTML 结构文件中提取数据:
<!DOCTYPE html>
<html>
<head>
<title>Smartproxy's Scraping Tutorial</title>
</head>
<body>
<h1 class="main-heading">What is a residential proxy?</h1>
<p class="description">A residential proxy is an intermediary server between you and the website you're trying to access. This server has an IP address provided by an Internet Service Provider (ISP), not a data center. Each residential IP is a real mobile or desktop device that pinpoints a certain physical location.</p>
<h2>Residential proxy features</h2>
<ul id="proxy-features">
<li class=>Premium quality and stability</li>
<li>Full anonymity and security</li>
<li>Large IP pool and worldwide targeting</li>
<li>Unlimited connections and threads</li>
</ul>
</body>
</html>
新建一个文本文件,命名为 website.html。用文本编辑器打开该文件,粘贴上述代码并保存。
接下来,在同一目录下创建一个 Python 脚本文件。随便给它起个名字,比如你最喜欢的汤类,例如 miso_soup.py。下面是代码片段:
# Import the BeautifulSoup library to use in the code
from bs4 import BeautifulSoup
# We tell the script to open and read the website.html file and store it in the content variable. In a real application, this would be an actual website, but we'll get to that later
with open('website.html', 'r') as f:
content = f.read()
# Here, we create a Beautiful Soup object using the built-in Python HTML parser
soup = BeautifulSoup(content, "html.parser")
# Let's say we want to find the <h1> heading from the website.html file. If you check it out, you'll see it has a class named "main-heading"
# To extract it, use the soup.find() method to find an element by its class
heading = soup.find(class_="main-heading")
# Finally, print the result. You can also write print(heading.text) to get rid of the HTML tags for a cleaner result
print(heading)
在终端中使用此命令运行代码:
python miso_soup.py
代码将读取 HTML 文档,对其进行解析,找到带有 main-heading 类的元素,并在终端中打印
What is a residential proxy?
如果你得到了相同的结果,那就太好了!您的设置工作正常,可以进入下一个步骤了。不过,如果遇到任何问题,请务必检查是否
- 您使用的是 pip 附带的最新 Python 版本,并且安装了 Beautiful Soup;
- miso_soup.py 和 website.html 文件位于同一目录(文件夹);
- 运行 Python 终端命令的目录与文件目录相同;
- 代码或文件名中没有任何错别字、拼写错误或其他错误。
基础知识就讲到这里。接下来,我们将解析一个实际网站的数据,您将看到我们如何使用您已经学到的知识并加以扩展。
为了了解对网站进行刮擦和解析的过程,我们将以 ScrapeMe 商店为目标。别担心,这不是一个真实的东西–它是一个为测试脚本而建立的示例网站,其功能与普通网店一模一样。唯一不同的是,它卖的是神奇宝贝。这是一个完美的起点,因为真实的网站可能会有反抓取措施,如验证码或速率限制,以防止多次自动请求。不过,这些措施可以借助代理服务器来规避,我们稍后将在真实世界的示例中使用代理服务器。
还有一件事–Beautiful Soup 需要一个朋友。该库本身无法搜刮数据。因此,我们还需要安装一个额外的 Python 软件包来进行 HTTP 请求:
pip install requests
简单地说,这个网络搜刮库能帮你向网站发出 HTTP 请求,获取 HTML 代码并返回给你。如果你想了解更多,可以点击此处阅读有关该库的信息。
再来测试一下我们的设置和库是否有效。我们将使用之前编写的代码并对其进行修改,以便从实际网站而不是文件中获取数据:
from bs4 import BeautifulSoup
# Import the requests library
import requests
# Define a URL to scrape from. Then, use the requests.get() method from the requests library to make an HTTP request to the website and get a result
url = "https://scrapeme.live/shop/"
response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")
# Remove this line, as we aren't picking a specific element and want to get the whole website
# heading = soup.find(class_="main-heading")
# Once again, we print the result
print(soup)
运行上述代码后,整个 HTML 页面就会打印在终端中。让我们看看如何修改这段代码,从页面中提取特定的 HTML 元素,获取更多相关信息。
通过 ID 或类名查找元素
网络解析中最常见的任务就是在 HTML 中查找元素。幸运的是,大多数元素都有属性来帮助相互识别。这些属性可以是开发人员决定的任何内容,但最常见的是 ID 和类属性。
让我们尝试一项简单的任务–列出主页上所有神奇宝贝的名称。使用 Chrome 浏览器开发工具(右键单击页面→检查)或相应的网页浏览器检查网站源代码。打开的窗口将显示页面的 HTML。列表中的第一个项目是 Bulbasaur。你可以尝试在代码中找到它,或者使用元素选择器,然后点击网站上的名称。这将跳转到该元素所在的 HTML 部分。
您需要的 HTML 元素有一个名为 woocommerce-loop-product__title 的类名。如果查看其他产品,可以发现它们都有相同的 HTML 类名。让我们编写一个简单的循环,浏览这些 HTML 元素并打印出来:
from bs4 import BeautifulSoup
import requests
url = "https://scrapeme.live/shop/"
response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")
# Instead of soup.find(), we use soup.find_all() to get all elements with the same class name
titles = soup.find_all(class_="woocommerce-loop-product__title")
# Loop through all of the results and print the text content
for title in titles:
print(title.text)
您将在终端中看到一个包含 16 个项目的列表。恭喜你,你刚刚解析了一个真实网站的数据!你还可以对脚本进行改动,看看还能提取出哪些内容,方法是改变 "美丽小汤 "应尝试查找的类别
搜索多个网页
您将在终端中看到一个包含 16 个项目的列表。恭喜你,你刚刚解析了一个真实网站的数据!你还可以对脚本进行修改,看看通过改变美丽小汤应尝试查找的类别,还能提取出哪些内容。
搜索多个网页
你已经成功打印出了 16 只神奇宝贝的名字,但如果你想把它们都抓住怎么办?问题在于商店被分成了多个 HTML 页面,而我们的脚本还不够聪明,无法浏览这些页面来获取所有信息。
让我们帮它一把,看看链接是如何工作的。每当您访问一个新页面时,URL 就会变成 …/shop/page/x/,其中 x 是页面编号。这对我们来说非常好,因为我们可以修改脚本,只需更改 URL 中的数字,就可以遍历每一页。具体操作如下
from bs4 import BeautifulSoup
import requests
url = "https://scrapeme.live/shop/"
# We move some elements around, as most of them need to be under a loop to be repeated every time the link changes
# As an example, let's create a loop for the first 10 pages, as scraping all of them will take a while
# The idea here is simple - open a page, scrape and parse the information, print it, go to the next page, repeat
for k in range(10):
# We append the /page/[number] to the URL string. The [number] will start at 1, and increase by 1 with each iteration
link = url + "page/"+str(k+1)
# The rest of the script is the same as before, except it is being repeated every loop
response = requests.get(link)
soup = BeautifulSoup(response.content, "html.parser")
titles = soup.find_all(class_="woocommerce-loop-product__title")
for title in titles:
print(title.text)
查找所有链接
该脚本的前提很简单,就是使用我们在上一个示例中已经知道的内容,并增加一个循环。不过,了解它是如何完成的还是很方便的,因为许多网站的首页很可能没有你需要的所有信息。要是这么简单就好了!
数据解析的另一个广泛用途是查找网站中的所有链接,也就是所谓的网络爬行。这对于各种原因都很有用,例如索引、查看竞争对手的链接、他们的网站结构以及许多其他用例。
还记得属性吗?这次,我们将不再使用属性作为 HTML 元素的标识符,而是改为查找属性。最常见的链接方式是通过 href 属性。因此,我们的任务非常简单–找到 HTML 网页中的所有 href 并打印它们的内容:
from bs4 import BeautifulSoup
import requests
url = "https://scrapeme.live/shop/"
response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")
# Links are defined in <a> tags, therefore tell the script to find all of them
links = soup.find_all('a')
for link in links:
# Use the .get() method to get the href attribute of an element
print(link.get('href'))
查找 HTML 元素的子元素
有些网站就是不愿意与你的脚本做朋友。虽然可以轻而易举地抓取和解析具有干净、准确的类属性的网站,但在很多情况下,HTML 元素是没有属性的。这就需要采用不同的方法–我们必须针对父元素及其子元素!
别担心,这并不像听起来那么糟糕。在 HTML 页面中,你可能已经注意到,一个元素下会有多个其他元素,如段落、表格或列表。将它们组合在一起的元素被称为父元素,而它下面的项目则被称为子元素。幸运的是,"美丽汤 "有一种浏览这种结构的方法,即使在最黑暗的缝隙中也能找到它。
让我们看看开发工具中的网页。右侧边栏有几个链接;如果检查它们,就会发现它们是无序列表结构,没有任何属性:
如果您想获取评论 RSS 链接,该如何告诉您的脚本如何找到它?方法如下
from bs4 import BeautifulSoup
import requests
url = "https://scrapeme.live/shop/"
response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")
# Find a parent element with a unique attribute that is closest to what you're trying to target. In this case, widget_meta is the class name of the <div> element with several children without attributes.
widget = soup.find(class_="widget_meta")
# Target the <ul> first. It's the 2nd child of the widget_meta class <div>; therefore, we write a [2] to tell it's position
list = widget.contents[2]
# Next, find the <a> element with the href you're looking for. It's the 5th child of the <ul> - make sure to count the <a> element under the 2nd <li>, as it's an indirect child of <ul>.
comments = list.contents[5]
# Finally, we simply take the <a> directly with [0] and get the href attribute value
link = comments.contents[0].get('href')
print(link)
从现实世界的网站中抓取和解析 HTML 数据
虽然我们在游乐场玩得很开心,但现在是时候进入真实世界了。这听起来可能有点吓人,但实际上,大多数真实网站的功能与我们在示例中使用的网站一模一样。它们遵循相同的 HTML 结构,包含 URL、具有可识别属性的特定元素等。关键的区别在于,它们可以保护自己的数据不被窃取。
网站可以跟踪来自单个 IP 地址的请求数量。人类通常速度较慢,会慢慢阅读网页。而脚本不会这样做,它会快速获取所需的内容,然后进入下一个任务。这种行为很容易识别,因为你的脚本会代表你发出多个请求,从而导致风险,比如你的 IP 被阻止访问网站。
解决办法是什么?代理服务器。代理服务器充当你和目标之间的中间人,允许你从不同于自己的 IP 地址发出请求。这样,您就可以创建多个请求,因为这些请求看起来就像是来自多个独立的 IP 地址,无法阻止或追踪到源头。
亚马逊是一个常用的数据搜刮和解析目标。它是一个庞大的市场,拥有大量关于产品、购买、定价、评论等方面的有价值信息,这些数据对任何企业或好奇者来说都非常有价值。点击此处查看如何抓取和解析产品标题、价格和评论等数据。
最佳实践
• 知识就是力量;你永远不可能知道太多关于数据解析的知识。以下是编写解析脚本时应牢记的一些有价值的提示:
• 许多网站会采取反抓取和解析措施,以防止您从一个 IP 地址发送过多请求。在脚本中使用代理就可以解决这个问题,因为你可以从全球多个地点发出请求,并确保请求来源的完全匿名性;
• 解析后的结果不一定总是干净的–因此,使用 result.text.strip() 等方法会很有帮助,因为这些方法只返回字符串值,而不包含任何额外的空格、符号、HTML 标记或其他会使数据看起来杂乱无章的额外麻烦;
• 你是否会将所有从终端解析出来的数据复制并粘贴到记事本中,然后交给你的数据分析师,然后想知道为什么他们对你侧目而视?他们也许能告诉你原因,因为使用结构化的 CSV、XML、JSON 或类似文件中的数据总是更方便。改进你的代码,让它将数据写入新文件,而不是终端;
• 确保遵循网站 robots.txt 文件的要求。该文件会告诉你哪些网页可以被网络抓取和刮擦,哪些不应该被碰触和放过。尊重机器人!
• 有些页面可能不容易在脚本中重复–它们的链接没有编号,也没有逻辑结构。因此,您可能需要准备一个链接数组,然后在其中循环。准备一个包含所有链接的文本文件,然后让脚本从中读取,提出请求,解析响应,并转到下一个链接。
• 动态网站可能更难抓取,因为它可能不会在加载后立即提供完整的 HTML 响应。随着越来越多的网站在 JavaScript 的帮助下建立,这种情况变得越来越常见。您需要调整 HTML 解析器脚本,使其稍有延迟,或者使用专为处理动态内容而设计的无头浏览器。
最后的思考
在本文中,您已经基本了解了数据解析的好处、如何使用 Beautiful Soup,并探讨了如何将其用于解析网络信息的示例。我们只是触及了基础知识,还有很多东西可以拓展。如果你想继续你的解析之旅,请阅读 Beautiful Soup 的官方文档,更深入地了解它。你还应该看看我们的代理选项,它们能帮助你无风险、无问题地搜索网络!