1.lxml
python lxml包用于解析XML和html文件,可以使用xpath和css定位元素,在爬虫中经常需要根据html标签来定位需要爬取的信息所在的位置,当然也可以使用正则表达式来匹配对应的html标签及标签中包含的内容,但是相信大部分小伙伴对正则表达式都深恶痛绝,想要写出来一个能够正确匹配到需要的信息的正则表达式实在是不容易,但是使用lxml就能够非常方便的匹配到我们想要的信息,再也不用为复杂的正则表达式发愁了。
使用lxml解析xml和html
关于如何使用lxml来获得我们想要的数据,这里介绍几种常用的方法
以一串xml代码为例
test_data = """
<div>
<ul>
<li class="item-0"><a href="link1.html" id="places_neighbours__row">9,596,960first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html" id="places_neighbours__row">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
<li class="good-0"><a href="link5.html">sixth item</a></li>
</ul>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
<time><year>2018</year></time>
</book>
<book>
<title lang="zh">Learning XML</title>
<price id="places_neighbours__row">39.95</price>
</book>
<book>
<title>python</title>
<price>40</price>
</book>
</div>
"""
lxml各种选择方法的使用,对上面xml代码进行解析()
/ 表示从跟标签开始
//表示从当前标签开始
* 通配符,选择所有
import lxml.html
html = lxml.html.fromstring(test_data)
html_data = html.xpath('//div/book[1]/title') #选择div下第一个book标签的title元素
html_data = html.xpath('//div/book[last()]') #将最后一个book元素选出
html_data = html.xpath('//div/book') # 选取div下的所有book标签
html_data = html.xpath('//book/title') # 选取book下的所有title标签
html_data = html.xpath('//title') #选取所有title标签
html_data = html.xpath('//div/book/title[@lang="zh"]')# 选择title属性含有lang且内容是zh的的元素
html_data = html.xpath('//book/title[@*]') #选择含有属性的title标签
html_data = html.xpath('//book/title/@*') #选择title下属性的值
html_data = html.xpath('//book/title/text()') # 使用内置text()函数,直接选择标签下的内容
html_data = html.xpath('//ul/li/a[@href="link1.html"]/text()') # 选取href属性为link1.html的标签中的内容
html_data = html.xpath('//a[@href="link1.html" and @id="places_neighbours__row"]/text()') #使用and,同时满足两个属性
html_data = html.xpath('//li[@class="item-0" or @class="item-1"]/a/text()') # 选取class=item-0或item-1的标签(实际两者都选)
html_data = html.xpath('//li[@class!="item-0" and @class!="item-1"]/a/text()') #同时不满足两个条件
html_data = html.xpath('//li/a[not(@id)]/text()') # 没有id属性
html_data = html.xpath('//div/book[last() - 1]/title/text()') # 选取倒数第二个book标签
html_data = html.xpath('//div/book[price > 30]/title/text()') #选择book标签中price标签的值大于39的
html_data = html.xpath('//li[starts-with(@class,"item")]/a/text()') # 将class属性前缀是item的li标签选出来
html_data = html.xpath('//title[contains(@lang,"en")]/text()') # 选择lang属性中包含"en"的title标签
html_data = html.xpath('//book/descendant::*/text()') # 选取book下的所有后续节点
# //book/ancestor::* 将祖先节点全部选出
print(html_data)
for i in html_data:
print(i,type(i))
在解析html代码的时候,能用到的基本语法差不多就是这些,已经足够我们在网页中定位到我们需要的信息。
下面是使用lxml爬取糗事百科段子的实例(真的很好爬取,适合用来爬虫入门的练习)
通过lxml实现一个简易爬虫
这里我们写一个爬取糗事百科段子的一个简单爬虫,通过lxml来选择我们需要爬取的内容,定位到内容在网页中的位置。
实现爬虫的基本思路:1.获取网站的源码 2.对网站源码进行解析,定位到需要爬取的信息的位置 3.爬取我们需要的信息
下面是爬虫的代码,代码的思路为:1.初始化,设置基本参数 2.爬取1-10页的数据,每一页对应的网址不一样,因此需要生成一个下载列表 3.定位到所需的数据并下载数据 4.将爬取的内容保存到文件中。
import lxml.html
import requests
class QiuBaiSpider:
def __init__(self):
# 爬取的网页,{}中为需要填入的对应的页码
self.base_url = 'https://www.qiushibaike.com/8hr/page/{}/'
# 生成下载的列表
def make_download_lists(self,page):
return [self.base_url.format(i) for i in range(page[0],page[1]+1)]
def download_content(self,base_url):
# url = self.base_url.format(page)
result = requests.get(base_url)
html = lxml.html.fromstring(result.text)
# 找到糗事百科信息在源码中的位置
content = html.xpath('//div[@class="content"]/span/text()')
return content
def save_to_file(self,result,page):
with open('qiubai第' + page + '页.txt','w',encoding='utf-8') as f:
for i in result:
f.write(i)
# 保存文件是生成与爬取网页对应的页码
def make_page_num(self,page):
return [i for i in range(page[0],page[1]+1)]
# 爬取的运行函数,实现爬取的逻辑
def run(self,page):
list = self.make_download_lists(page=page) # 生成下载列表
page = self.make_page_num(page=page) # 生成对应的页码
for url in list:
content = self.download_content(base_url=url) # 获取到网页中的所有段子
print(content)
i = list.index(url) # 生成下载的对应的页码
self.save_to_file(content,page=str(page[i])) #保存到文件,页码为爬取的页码
print('爬取完毕......')
if __name__ == '__main__':
qiubai = QiuBaiSpider()
qiubai.run(page=[1,10])
这样就实现了一个能爬取糗事百科段子简单爬虫,虽然离真正的爬虫还有些遥远,但总算是迈出了第一步。