返回博客
指南
Mihai MaximLast updated on Mar 31, 20262 min read

Parsel:如何在 Python 中从 HTML 中提取文本

Parsel:如何在 Python 中从 HTML 中提取文本

简介

网络爬虫是指利用脚本或程序从网站自动收集数据的过程。它用于提取文本、图像及其他类型的数据,这些信息可用于研究、数据分析或市场分析等多种用途。

如今,关于使用 Python 进行网页抓取的解决方案不胜枚举。Selenium 和 Scrapy 是最广泛使用且广受欢迎的库。虽然这些工具非常适合处理复杂的抓取任务,但对于日常使用而言,它们可能会让人感到有些难以驾驭。

这时,Parsel 这款小巧的爬取库便应运而生。这个轻量级且易于学习的库非常适合小型项目,对于刚接触网页爬取的新手来说更是理想之选。它能够解析 HTML,并利用 CSS 和 XPath 选择器提取数据,对于任何希望快速轻松地从网络上收集信息的“数据爱好者”而言,都是绝佳的工具。

请系好安全带,准备好学习如何使用这个库,跟我一起踏上这场自动化数据采集的冒险之旅。让我们开始抓取吧!

Parsel 入门指南

您可以通过以下命令安装 Parsel 库:

pip install parsel

现在让我们直接进入一个示例项目,从这个简单的网站 https://www.scrapethissite.com/pages/simple/ 抓取所有国家/地区数据。

要获取网站的 HTML 内容,你需要发起一个 HTTP GET 请求。

我们将使用 Python 的 “requests” 库来发送 HTTP 请求,因此请确保已通过以下命令安装该库:

pip install requests

现在您可以获取 HTML 内容并将其写入文件:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

with open("out.html", "w", encoding="utf-8") as f:

f.write(response.text)

并查看其结构:

我们的数据存储在类似于这样的结构中:

<div class="col-md-4 country">

   <h3 class="country-name">

       <i class="flag-icon flag-icon-af"></i>

       Afghanistan

   </h3>

   <div class="country-info">

       <strong>Capital:</strong> <span class="country-capital">Kabul</span><br>

       <strong>Population:</strong> <span class="country-population">29121286</span><br>

       <strong>Area (km<sup>2</sup>):</strong> <span class="country-area">647500.0</span><br>

   </div>

</div><!--.col-->

要编写选择器,你需要将原始 HTML 传递给 Parsel:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text = raw_html)

现在我们可以开始编写选择器了。

使用 CSS 选择器提取文本

你可以使用以下代码输出第一个国家的首都:

parsel_dom = parsel.Selector(text=raw_html)

first_capital = parsel_dom.css(".country-capital::text").get()

print(first_capital)

// Output

Andorra la Vella

parsel_dom.css(".country-capital::text").get() will select the inner text of the first element that has the country-capital class.

你可以使用以下代码打印所有国家名称:

countries_names = filter(lambda line: line.strip() != "", parsel_dom.css(".country-name::text").getall())

for country_name in countries_names:

   print(country_name.strip())

// Output

Andorra

United Arab Emirates

Afghanistan

Antigua and Barbuda

Anguilla

. . .

parsel_dom.css(".country-name::text").getall() will select the inner texts of all the elements that have the "country-name" class.

请注意,我们需要对输出结果进行一些清理。这是因为所有带有“.country-name”类的元素内部都嵌套了一个<i>标签。此外,国家名称周围还带有许多尾随空格。

<h3 class="country-name">

 <i class="flag-icon flag-icon-ae"></i> //this is picked up as an empty string

  United Arab Emirates // this is picked up as “  United Arab Emirates  “

</h3>

现在,让我们编写一个脚本,使用 CSS 选择器提取所有数据:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text=raw_html)

countries = parsel_dom.css(".country")

countries_data = []

for country in countries:

  country_name = country.css(".country-name::text").getall()[1].strip()

  country_capital = country.css(".country-capital::text").get()

  country_population = country.css(".country-population::text").get()

  country_area = country.css(".country-area::text").get()

  countries_data.append({

     "name": country_name,

     "capital": country_capital,

     "population": country_population,

     "area": country_area

  })

for country_data in countries_data:

  print(country_data)

// Outputs

{'name': 'Andorra', 'capital': 'Andorra la Vella', 'population': '84000', 'area': '468.0'}

{'name': 'United Arab Emirates', 'capital': 'Abu Dhabi', 'population': '4975593', 'area': '82880.0'}

{'name': 'Afghanistan', 'capital': 'Kabul', 'population': '29121286', 'area': '647500.0'}

... 

使用 XPath 选择器提取文本

XPath 是一种用于从 XML 文档中选择节点的查询语言。它代表 XML 路径语言(XML Path Language),并使用类似于 URL 的路径表示法来遍历 XML 文档的元素和属性。XPath 表达式可用于选择单个元素、一组元素或元素的特定属性。 XPath 主要应用于 XSLT,但也可用于遍历任何 XML 类语言文档(如 HTML 或 SVG)的文档对象模型(DOM)。

XPath 初看可能令人望而生畏,但一旦掌握了基本概念和语法,入门其实相当简单。我们的 XPath 选择器指南(https://www.webscrapingapi.com/the-ultimate-xpath-cheat-sheet)是一份非常实用的参考资料。

现在让我们尝试一些选择器:

以下是打印第一个大写字母的方法:

parsel_dom = parsel.Selector(text=raw_html)

first_capital = parsel_dom.xpath('//*[@class="country-capital"]/text()').get()

print(first_capital)

// Output

Andorra la Vella

以及所有国家名称:

countries_names = filter(lambda line: line.strip() != "", 

parsel_dom.xpath('//*[@class="country-name"]//text()').getall())

for country_name in countries_names:

  print(country_name.strip())

// Output

Andorra la Vella

Abu Dhabi

Kabul

St. John's

The Valley

Tirana

...

让我们使用 XPath 选择器重写该脚本:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text=raw_html)

countries = parsel_dom.xpath('//div[contains(@class,"country")][not(contains(@class,"country-"))]')

countries_data = []

for country in countries:

 country_name = country.xpath(".//h3/text()").getall()[1].strip()

 country_capital = country.xpath(".//span/text()").getall()[0]

 country_population = country.xpath(".//span/text()").getall()[1]

 country_area = country.xpath(".//span/text()").getall()[2]

 countries_data.append({

    "name": country_name,

    "capital": country_capital,

    "population": country_population,

    "area": country_area

 })

for country_data in countries_data:

 print(country_data)

// Output

{'name': 'Andorra', 'capital': 'Andorra la Vella', 'population': '84000', 'area': '468.0'}

{'name': 'United Arab Emirates', 'capital': 'Abu Dhabi', 'population': '4975593', 'area': '82880.0'}

{'name': 'Afghanistan', 'capital': 'Kabul', 'population': '29121286', 'area': '647500.0'}

...

删除元素

删除元素很简单。只需将 drop 函数应用于选择器即可:

selector.css(".my_class").drop()

让我们编写一个脚本,从每个国家/地区中移除“人口”字段,以此演示这一功能:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text=raw_html)

countries = parsel_dom.css(".country")

for country in countries:

 country.css(".country-population").drop()

 country.xpath(".//strong")[1].drop()

 country.xpath(".//br")[1].drop()

countries_without_population_html = parsel_dom.get()

with open("out.html", "w", encoding="utf-8") as f:

  f.write(countries_without_population_html)

导出数据

完成数据抓取后,考虑如何保存数据至关重要。存储此类数据的两种常见格式是 .json 和 .csv。不过,您应根据项目需求选择最合适的格式。

将数据导出为 .json

JSON(JavaScript 对象表示法)是一种轻量级的数据交换格式,既便于人类阅读和编写,也便于机器解析和生成。它常用于在 Web 应用程序与服务器之间,或 Web 应用程序的不同组件之间交换数据。 JSON 与 Python 字典相似,同样用于以键值对的形式存储数据,且可用于存储和访问相同类型的数据,并具有相同的结构。

使用 json 库可将 Python 字典数组导出为 .json 格式:

import json

countries_dictionaries = [

{'name': 'Andorra', 'capital': 'Andorra la Vella', 'population': '84000', 'area': '468.0'},

{'name': 'United Arab Emirates', 'capital': 'Abu Dhabi', 'population': '4975593', 'area': '82880.0'}

]

json_data = json.dumps(countries_dictionaries, indent=4)

with open("data.json", "w") as outfile:

   outfile.write(json_data)

// data.json

[

   {

       "name": "Andorra",

       "capital": "Andorra la Vella",

       "population": "84000",

       "area": "468.0"

   },

   {

       "name": "United Arab Emirates",

       "capital": "Abu Dhabi",

       "population": "4975593",

       "area": "82880.0"

   }

]

将数据导出为 .csv

CSV 是一种在文本文件中存储数据的简便方式,其中每行代表一个数据行,每个值由逗号分隔。它常用于电子表格或数据库程序中。Python 通过其 csv 模块,对处理 CSV 文件提供了出色的内置支持。CSV 模块最强大的功能之一是 DictWriter 类,它允许您以简单的方式将 Python 字典写入 CSV 文件。 字典的键将作为 CSV 文件中的列标题,而键值对中的值将作为行中的对应数据写入文件。

以下是使用 csv 库将 Python 字典数组导出为 .csv 文件的方法。

countries_dictionaries = [

{"name": "John Smith", "age": 35, "city": "New York"},

{"name": "Jane Doe", "age": 28, "city": "San Francisco"}

]

with open("data.csv", "w") as outfile:

   writer = csv.DictWriter(outfile, fieldnames=countries_dictionaries[0].keys())

   writer.writeheader()

   for row in countries_dictionaries:

       writer.writerow(row)

// data.csv

name,age,city

John Smith,35,New York

Jane Doe,28,San Francisco

总结

在本文中,我们探讨了 Python 中 Parsel 库的应用。我们看到了使用 Parsel 提供的 CSS 和 XPath 选择器从网页中提取数据是多么简单。总体而言,Parsel 为网络爬虫提供了高效且多功能的解决方案。如果您对自动化数据采集感兴趣,绝对值得一试。

想进一步了解网页抓取吗?欢迎了解我们的产品 WebScrapingAPI,探索如何将您的数据提取技能提升到新高度。我们功能强大的 API 专为帮助您克服网页抓取中最常见的挑战而设计,例如避免 IP 封禁或加载 JavaScript。最棒的是?您可以免费试用!

关于作者
Mihai Maxim, 全栈开发工程师 @ WebScrapingAPI
Mihai Maxim全栈开发工程师

米海·马克西姆(Mihai Maxim)是 WebScrapingAPI 的全栈开发工程师,他在产品各领域均有贡献,并协助为该平台构建可靠的工具和功能。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网络数据。