前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >lxml网页抓取教程

lxml网页抓取教程

原创
作者头像
用户7850017
修改2021-10-15 17:51:22
3.8K0
修改2021-10-15 17:51:22
举报

使用lxml处理XML及网页抓取

在本教程中,我们会学习lxml库和创建XML文档的基础知识,然后会处理XML和HTML文档。最后,我们将利用以上所学,融会贯通,看看如何使用lxml提取数据。本教程的每一步都配有实用的Python lxml示例。

阅读人群

​本教程适用于对Python、XML和HTML有基本的了解的开发人员。简单地说,如果您知道XML中的属性是什么,那么就足以理解本文。

本教程使用Python3代码段,但所有内容都可以在Python2上运行,只需进行少量更改。

Python中的lxml是什么?

lxml是在Python中处理XML和HTML最快且功能丰富的库之一。该库本质上是C库libxml2和libxslt的封装。因此结合了C库的速度和Python的简单性。

使用Python lxml库,可以创建、解析和查询XML和HTML文档。它依赖于许多其他复杂的包,如Scrapy。

#安装

下载和安装lxml库的最佳方法是去Python Package Index(PyPI)下载

如果您使用的是Linux(基于debian),只需运行:

  sudo apt-get install python3-lxml

另一种方法是使用pip包管理器。这适用于Windows、Mac和Linux:

  pip3 install lxml

在Windows上,假设您正在运行Python3,只需使用pip install lxml。

#创建一个简单的XML文档

任何XML或任何符合XML的HTML都可以看作一棵树。一棵树有根和树枝。树的每个分支可以具有更多分支。所有这些分支和根都分别表示一个Element。

一个非常简单的XML文档如下所示:

<root>
      <branch>
          <branch_one>
          </branch_one>
          <branch_one>
          </branch_one>
     <branch>
</root>

如果HTML是兼容XML的,它将遵循相同的概念。

请注意,HTML可能兼容也可能不兼容XML。例如,如果HTML的<br>没有相应的结束标记,它仍然是有效的HTML,但它不会是有效的XML。

在本教程的后半部分,我们将看看如何处理这些情况。接下来让我们专注于兼容XML的HTML。

#元素类

使用python lxml创建XML文档,第一步是导入lxml的etree模块:

>>> from lxml import etree

每个XML文档都以根元素开始。可以使用元素类型创建。元素类型是一个灵活的容器对象,可以存储分层数据。可以描述为字典和列表之间的交叉。

在这个python lxml示例中,目标是创建一个兼容XML的HTML。这意味着根元素的名称将是html:

>>> root = etree.Element("html")

同样,每个html都会有一个头部和一个主体:

>>> head = etree.Element("head")
>>> body = etree.Element("body")

要创建父子关系,我们可以简单地使用append()方法。

>>> root.append(head)
>>> root.append(body)

tostring()函数的帮助下,这个文档可以被序列化并输出到终端。此函数需要一个强制参数,即文档的根。我们可以选择将pretty_print设置为True以使输出更具可读性。

请注意,tostring()序列化程序会实际返回字节。这可以通过调用decode()转换为字符串:

>>> print(etree.tostring(root, pretty_print=True).decode())

#子元素类

创建一个Element对象并调用append()函数会使代码变得混乱和不可读。最简单的方法是使用SubElement类型。它的构造函数有两个参数——父节点和元素名称。使用SubElement,以下两行代码可以替换为一行。

body = etree.Element("body")
root.append(body)
# is same as
body = etree.SubElement(root,"body")

#设置文本和属性

使用lxml库设置文本非常容易。ElementSubElement的每个实例都公开了两个方法——textset,前者用于指定文本,后者用于设置属性。以下是示例:

para = etree.SubElement(body, "p")
para.text="Hello World!"

同样,可以使用键值约定设置属性:

para.set("style", "font-size:20pt")

要注意的是,可以在SubElement的构造函数中传递该属性:

para = etree.SubElement(body, "p", style="font-size:20pt", id="firstPara")
para.text = "Hello World!"

这种方法的节省了代码行数,代码可读性也更强。这是完整的代码。将它保存在一个python文件中并运行它。它将输出一个HTML,它也是一个格式良好的XML。

from lxml import etree

root = etree.Element("html")
head = etree.SubElement(root, "head")
title = etree.SubElement(head, "title")
title.text = "This is Page Title"
body = etree.SubElement(root, "body")
heading = etree.SubElement(body, "h1", style="font-size:20pt", id="head")
heading.text = "Hello World!"
para = etree.SubElement(body, "p",  id="firstPara")
para.text = "This HTML is XML Compliant!"
para = etree.SubElement(body, "p",  id="secondPara")
para.text = "This is the second paragraph."

etree.dump(root)  # prints everything to console. Use for debug only

请注意,这里我们使用了etree.dump()而不是调用etree.tostring()。不同之处在于dump()只是将所有内容写入控制台而不返回任何内容,tostring()用于序列化并返回一个字符串,您可以将其存储在变量中或写入文件。dump()仅适用于调试,不应用于任何其他目的。

在代码段的底部添加以下几行并再次运行它:

with open(‘input.html’, ‘wb’) as f:
f.write(etree.tostring(root, pretty_print=True)

代码会将内容保存到您运行脚本的同一文件夹中的input.html。同样,这是一个格式良好的XML,可以看作XML或HTML。

如何在Python中使用LXML

解析XML文件?

上一节是关于创建XML文件的Python lxml教程。在本节中,我们将研究如何使用lxml库遍历和操作现有的XML文档。

在我们继续之前,将以下代码段保存为input.html。

<html>
    <head>
      <title>This is Page Title</title>
    </head>
    <body>
       <h1 style="font-size:20pt" id="head">Hello World!</h1>
       <p id="firstPara">This HTML is XML Compliant!</p>
       <p id="secondPara">This is the second paragraph.</p>
    </body>
</html>

解析XML文档时,结果是内存中的ElementTree对象。

原始XML内容可以在文件系统或字符串中。如果它在文件系统中,则可以使用parse方法加载它。请注意,parse方法将返回一个ElementTree类型的对象。要获取根元素,只需调用getroot()方法。

from lxml import etree

tree = etree.parse('input.html')
elem = tree.getroot()
etree.dump(elem) #prints file contents to console

lxml.etree模块公开了另一种可用于有效解析xml字符串中内容的方法—fromstring()

xml ='<html><body>Hello</body></html>'
root = etree.fromstring(xml)
etree.dump(root)

这里要注意的一个重要区别是fromstring()方法会返回一个元素对象。无需调用getroot()。

如果您想深入了解解析,可以查看BeautifulSoup教程的详细内容:

这是一个用于解析HTML和XML文档的Python包。但是为了快速回答BeautifulSoup中的lxml是什么,lxml可以使用BeautifulSoup作为解析器后端。同样,BeautifulSoup可以使用lxml作为解析器。

在XML中查找元素

从广义上讲,有两种使用Python lxml库查找元素的方法。第一种是使用Python lxml查询语言:XPath和ElementPath。例如,以下代码将返回第一个段落元素。

请注意,选择器与XPath非常相似。另请注意,未使用根元素名称,因为elem包含XML树的根。

tree = etree.parse('input.html')
elem = tree.getroot()
para = elem.find('body/p')
etree.dump(para)

# Output
# <p id="firstPara">This HTML is XML Compliant!</p>

类似地,findall()将返回与选择器匹配的所有元素的列表。

elem = tree.getroot()
para = elem.findall('body/p')
for e in para:
    etree.dump(e)
 
# Outputs
# <p id="firstPara">This HTML is XML Compliant!</p>
# <p id="secondPara">This is the second paragraph.</p>

选择元素的第二种方法是直接使用XPath。熟悉XPath的开发人员更容易使用这种方法。此外,XPath可用于使用标准XPath语法返回元素的实例、文本或任何属性的值。

para = elem.xpath('//p/text()')
for e in para:
    print(e)

# Output
# This HTML is XML Compliant!
# This is the second paragraph.

使用lxml.html处理HTML

在本文中,我们一直在使用兼容XML的格式良好的HTML。很多时候情况并非如此。对于这些场景,您可以简单地使用lxml.html而不是lxml.etree。

请注意,不支持直接从文件中读取。文件内容应首先以字符串形式读取。这是从同一HTML文件输出所有段落的代码。

from lxml import html
with open('input.html') as f:
     html_string = f.read()
tree = html.fromstring(html_string)
para = tree.xpath('//p/text()')
for e in para:
     print(e)

# Output
# This HTML is XML Compliant!
# This is the second paragraph

lxml网页抓取教程

现在我们知道如何解析和查找XML和HTML中的元素,唯一缺少的部分是获取网页的HTML。

为此,“requests”库是一个不错的选择。它可以使用pip包管理器安装:

pip install requests

一旦安装了requests库,就可以使用简单的get()方法检索任何网页的HTML。示例如下:

import requests

response = requests.get('http://books.toscrape.com/')
print(response.text)
# prints source HTML

可以与lxml结合以检索所需的任何数据。

这是一个输出维基百科国家列表的简单示例:

import requests
from lxml import html

response = requests.get('https://en.wikipedia.org/wiki/List_of_countries_by_population_in_2010')

tree = html.fromstring(response.text)
countries = tree.xpath('//span[@class="flagicon"]')
for country in countries:
    print(country.xpath('./following-sibling::a/text()')[0])

在这段代码中,response.text返回的HTML被解析为变量树。可以使用标准XPath语法进行查询,连接XPath。请注意,xpath()方法返回一个列表,因此在此代码片段中仅获取第一项。

这可以很容易地扩展为从HTML读取任何属性。例如,以下修改后的代码输出结果为国旗的国家名称和图像URL。

for country in countries:
    flag = country.xpath('./img/@src')[0]
    country = country.xpath('./following-sibling::a/text()')[0]
    print(country, flag)

结论

在这个Python lxml教程中,介绍了使用lxml库处理XML和HTML。Python lxml库是一个轻量级、快速且功能丰富的库。可用于创建XML文档、读取现有文档和查找特定元素。这个库对于XML和HTML文档同样强大。结合Requests库,它也可以很容易地用于网页抓取。

您可以阅读使用Selenium或其他有用库(例如Beautiful Soup)的文章并了解有关网络抓取的更多信息。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用lxml处理XML及网页抓取
  • 阅读人群
  • Python中的lxml是什么?
  • 在XML中查找元素
  • lxml网页抓取教程
  • 结论
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档