义上讲,爬虫只负责抓取,也就是下载网页。而实际上,爬虫还要负责从下载的网页中提取我们想要的数据,即对非结构化的数据(网页)进行解析提取出结构化的数据(有用数据)。
所以说,网页下载下来只是第一步,还有重要的一步就是数据提取。不同的爬虫想要的数据不一样,提取的数据也就不一样,但提取方法都是类似的。
最简单的提取数据的方法,就是使用正则表达式,此种方法简单,提取的逻辑也不能复杂,不然写出的正则表达式就晦涩难懂,甚至不能提取复杂的数据结构。
最终,老猿经过多年的使用经验,选择了lxml和xpath来解析网页提取结构化数据。顺便说一下 BeautifulSoup,它也是一个很棒的解析HTML的工具,可以使用多个解析器,比如Python标准库的parser,但是速度比较慢,也可以使用lxml作为解析器,但是它的使用方法、API跟lxml不太一样。使用下来,还是lxml的API更舒服。
lxml 对C语言库 libxml2和 libxslt进行绑定,提供了Pythonic的API,它有一些主要特点:
总结为一句话就是,C语言的速度和Python的简易相结合的神器。
lxml有两大部分,分别支持XML和HTML的解析:
lxml.etree可以用来解析RSS feed,它就是一个XML格式的文档。然而爬虫抓取的绝大部分都是html网页,所以,我们这里主要讲述lxml.html解析网页的方法。
我们下载得到的网页就是一串html字符串,如何把它输入给lxml.html模块,从而生成html文档的树结构呢?
该模块提供了几种不同的方法:
下面我们通过具体示例来说明上面几个方法的不同。
document_fromstring 的使用方法
In [1]: import lxml.html as lh In [2]: z = lh.document_fromstring('<span>abc</span><span>xyz</span>') # 可以看到,它自动加了根节点<html> In [3]: z Out[3]: <Element html at 0x7fc410667b88> In [4]: z.tag Out[4]: 'html' # 还加了<body>节点 In [5]: z.getchildren() Out[5]: [<Element body at 0x7fc4101a3ae8>] # 把字符串的两个节点放在了<body>里面 In [6]: z.getchildren()[0].getchildren() Out[6]: [<Element span at 0x7fc410092bd8>, <Element span at 0x7fc410667c28>]
fragment_fromstring 的使用
In [11]: z = lh.fragment_fromstring(‘<div>abc</div><div>xyz</div>’) --------------------------------------------------------------------------- ParserError Traceback (most recent call last) <ipython-input-11-a11f9a0f71d1> in <module>() ----> 1 z = lh.fragment_fromstring(‘<div>abc</div><div>xyz</div>’) ~/.virtualenvs/py3.6/lib/python3.6/site-packages/lxml/html/__init__.py in fragment_fromstring(html, create_parent, base_url, parser, **kw) 850 raise etree.ParserError( 851 “Multiple elements found (%s)” --> 852 % ‘, ‘.join([_element_name(e) for e in elements])) 853 el = elements[0] 854 if el.tail and el.tail.strip(): ParserError: Multiple elements found (div, div) # 可以看到,输入是两个节点(element)时就会报错 # 如果加上 create_parent 参数,就没问题了 In [12]: z = lh.fragment_fromstring('<div>abc</div><div>xyz</div>', create_parent='p') In [13]: z.tag Out[13]: 'p' In [14]: z.getchildren() Out[14]: [<Element div at 0x7fc40a41a818>, <Element div at 0x7fc40a41aea8>]
fragments_fromstring 的使用
# 输入字符串含有一个节点,则返回包含这一个节点的列表 In [17]: lh.fragments_fromstring('<div>abc</div>') Out[17]: [<Element div at 0x7fc40a124ea8>] # 输入字符串含有多个节点,则返回包含这多个节点的列表 In [18]: lh.fragments_fromstring('<div>abc</div><div>xyz</div>') Out[18]: [<Element div at 0x7fc40a124b88>, <Element div at 0x7fc40a124f98>]
fromstring 的使用
In [27]: z = lh.fromstring('<div>abc</div><div>xyz</div>') In [28]: z Out[28]: <Element div at 0x7fc40a0eb368> In [29]: z.getchildren() Out[29]: [<Element div at 0x7fc410135548>, <Element div at 0x7fc40a0eb2c8>] In [30]: type(z) Out[30]: lxml.html.HtmlElement
这里,fromstring输入的如果是多个节点,它会给加一个父节点并返回。但是像html网页都是从节点开始的,我们使用fromstring() 和 document_fromstring() 都可以得到完整的网页结构。
从上面代码中我们可以看到,那几个函数返回的都是HtmlElement对象,也就是说,我们已经学会了如何从html字符串得到HtmlElement的对象,下一节我们将学习如何操作HtmlElement对象,从中提取我们感兴趣的数据。
发送HTTP请求:首先,你需要向目标网页发送HTTP请求以获取其HTML内容。这可以通过Java的内置库java.net.HttpURLConnection或者使用更高级的库如Apache Http Client OkHttp等来完成。
·读取响应内容:一旦你发送了请求并收到了响应,你需要读取响应的内容,这通常是HTML格式的字符串。
·解析HTML:然后,你需要解析HTML字符串以提取所需的信息,这可以通过正则表达式来完成。但通常建议使用专门的HTML解析库,如Jsoup。Jsoup提供了一种非常方便的方式来解析HTML文档,并可以通过类似于CSS或jQuery的选择器语法来提取和操作数据。
·如果你需要处理更复杂的网页或进行更高级的网页抓取和解析任务,你可能还需要考虑使用如Selenium这样的浏览器自动化工具来模拟真实的浏览器行为。但是请注意,频繁或大规模地抓取网页可能会违反网站的使用条款甚至可能构成法律问题。
解析HTML文档,可以使用一些编程语言中的HTML解析库或工具。以下是一些常用的方法:
from bs4 import BeautifulSoup
# 读取HTML文档
with open('example.html', 'r') as file:
html = file.read()
# 创建BeautifulSoup对象
soup = BeautifulSoup(html, 'html.parser')
# 使用BeautifulSoup对象提取数据
# 例如,提取所有的链接
links = soup.find_all('a')
for link in links:
print(link.get('href'))
// 读取HTML文档
var html = document.documentElement.innerHTML;
// 使用DOM解析器提取数据
// 例如,提取所有的链接
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
console.log(links[i].getAttribute('href'));
}
无论你选择哪种方法,解析HTML文档的关键是了解HTML的结构和标签,并使用相应的解析器或工具来提取所需的数据。
当你解析HTML文档时,你可能会遇到以下一些常见的任务和技术:
总的来说,解析HTML文档需要一定的HTML知识和编程技巧。你需要了解HTML的结构和标签,选择合适的解析器或工具,使用选择器来定位元素,提取所需的数据,并处理特殊情况。通过不断练习和实践,你将能够更熟练地解析HTML文档并提取所需的数据。
*请认真填写需求信息,我们会在24小时内与您取得联系。