python抓取网页数据(Python的lxml模块是什么意思?如何把网页解析成DOM树 )
优采云 发布时间: 2021-09-19 04:04python抓取网页数据(Python的lxml模块是什么意思?如何把网页解析成DOM树
)
Python的lxml模块是一个非常易于使用的高性能HTML和XML解析工具。通过解析网页,爬虫可以轻松地从网页中提取所需的数据。Lxml是基于C语言的libxml2和libxslt库开发的,速度非常快
使用lxml提取web页面数据的过程
要从网页提取数据,使用lxml需要两个步骤:
生成DOM树
如上所述,有三种方法可以将网页解析为DOM树。选择有困难的学生将很难。什么样的好选择?别担心,让我们一个一个地探索。让我通过一个示例分析以下HTML代码:
<p class="p_1 item">item_1
item_2
item_3
</p>
使用etree。Fromstring()函数
让我们看一下这个函数(docstring)的描述:
In [3]: etree.fromstring?
Signature: etree.fromstring(text, parser=None, *, base_url=None)
Call signature: etree.fromstring(*args, **kwargs)
Type: cython_function_or_method
String form:
Docstring:
fromstring(text, parser=None, base_url=None)
Parses an XML document or fragment from a string. Returns the
root node (or the result returned by a parser target).
To override the default parser with a different parser you can pass it to
the ``parser`` keyword argument.
The ``base_url`` keyword argument allows to set the original base URL of
the document to support relative Paths when looking up external entities
(DTD, XInclude, ...).
此函数将输入HTML解析为DOM树并返回根节点。它对输入字符串文本有任何要求吗?首先,它必须是合法的HTML字符串,然后让我们来看看下面的例子:
In [19]: html = '''
...:
...: <p class="p_1 item">item_1
...:
item_2
...:
...:
...:
item_3
...:
...: '''
In [20]: etree.fromstring(html)
Traceback (most recent call last):
File "/home/veelion/.virtualenvs/py3.6/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3267, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "", line 1, in
etree.fromstring(html)
File "src/lxml/etree.pyx", line 3213, in lxml.etree.fromstring
File "src/lxml/parser.pxi", line 1877, in lxml.etree._parseMemoryDocument
File "src/lxml/parser.pxi", line 1758, in lxml.etree._parseDoc
File "src/lxml/parser.pxi", line 1068, in lxml.etree._BaseParser._parseUnicodeDoc
File "src/lxml/parser.pxi", line 601, in lxml.etree._ParserContext._handleParseResultDoc
File "src/lxml/parser.pxi", line 711, in lxml.etree._handleParseResult
File "src/lxml/parser.pxi", line 640, in lxml.etree._raiseParseError
File "", line 6
XMLSyntaxError: Extra content at the end of the document, line 6, column 1
</p>
报告错了!原因是我们的html是并置的
没有单独根节点的标记。然后将最外层添加到HTML
标签呢
In [22]: etree.fromstring('' + html + '')
Out[22]:
这样,将返回根节点,它是一个元素对象,标记是Div
总而言之,埃特里。Fromstring()需要最外层是单独的节点,否则将发生错误。该方法也适用于生成XML的DOM树
使用etree。HTML()函数
这个函数更像HTML。查看其文档字符串:
In [23]: etree.HTML?
Signature: etree.HTML(text, parser=None, *, base_url=None)
Call signature: etree.HTML(*args, **kwargs)
Type: cython_function_or_method
String form:
Docstring:
HTML(text, parser=None, base_url=None)
Parses an HTML document from a string constant. Returns the root
node (or the result returned by a parser target). This function
can be used to embed "HTML literals" in Python code.
To override the parser with a different ``HTMLParser`` you can pass it to
the ``parser`` keyword argument.
The ``base_url`` keyword argument allows to set the original base URL of
the document to support relative Paths when looking up external entities
(DTD, XInclude, ...).
就像两颗豌豆(etree.fromstring)一样
接口参数包括:
In [24]: etree.HTML(html)
Out[24]:
为两个并排的节点输入HTML没有问题。等等,返回的根节点对象元素的标记是HTML?使用etree将其还原为HTML代码。Tostring():
In [26]: print(etree.tostring(etree.HTML(html)).decode())
<p class="p_1 item">item_1
item_2
item_3
In [27]: print(html)
item_1
item_2
item_3
</p>
也就是说,etree。函数完成HTML代码片段并对其进行标记
使用lxml.html函数
html是Lxml的一个子模块。它封装了etree,更适合解析HTML网页。使用此子模块生成DOM树有几种方法:
他们的docstring可以在IPython中进行检查,这里不会列出。通常,我们可以使用最后一个fromstring()解析网页。这个fromstring()函数还将向示例HTML代码的前两个并行节点添加一个父节点div
在介绍了以上三种方法之后,我相信你有一个选择。它必须是lxml.html
因为它封装了HTML,所以它还有特殊的编写方法:
使用XPath提取数据
我们还以下面的HTML代码为例来了解如何定位节点和提取数据
<p class="p_1 item">item_1
item_2
item_3
</p>
首先,导入lxml.html模块以生成DOM树:
In [50]: import lxml.html as lh
In [51]: doc = lh.fromstring(html)
(1)通过标记属性定位节点)
例如,我们需要
此节点:
In [52]: doc.xpath('//div[@class="2"]')
Out[52]: []
In [53]: print(lh.tostring(doc.xpath('//div[@class="2"]')[0]).decode())
<p id="p3">item_3
</p>
(2)contains文法
HTML中有两种
标记的类收录项。如果要提取这两个项
标签,然后:
In [54]: doc.xpath('//p[contains(@class, "item")]')
Out[54]: [, ]
## 获取<p>的文本:
In [55]: doc.xpath('//p[contains(@class, "item")]/text()')
Out[55]: ['item_1', 'item_2']
(3)starts-使用语法
提取需求,如(2)),两个
标签的类别以p_uSO开头:
In [60]: doc.xpath('//p[starts-with(@class, "p_")]')
Out[60]: [, ]
## 获取<p>的文本:
In [61]: doc.xpath('//p[starts-with(@class, "p_")]/text()')
Out[61]: ['item_1', 'item_2']
(4)获取属性的值
例如,我们希望提取网页中的所有链接:
In [63]: doc.xpath('//@href')
Out[63]: ['/go-p3']
如果您对XPath有更聪明的用法,请与我们分享。谢谢