python之xpath和lxml模块
1. xpath介绍
1.1 基本概念
XPath(XML Path Language)是一种XML的查询语言,他能在XML树状结构中寻找节点。XPath 用于在 XML 文档中通过元素和属性进行导航xml是一种标记语法的文本格式,xpath可以方便的定位xml中的元素和其中的属性值。lxml是python中的一个包,这个包中包含了将html文本转成xml对象,和对对象执行xpath的功能。
1.2 结点的关系
1 xml_content = '''
2 <bookstore>
3 <book>
4 <title lang='eng'>Harry Potter</title>
5 <author>K.Rowing</author>
6 <year>2005</year>
7 <price>29<price>
8 </book>
9 </bookstore>
10
节点的关系
父(Parent) book元素是title、author、year、price元素的父
子(Children) title、author、year、price都是book元素的子
同胞(Sibling) title、author、year、price都是同胞
先辈(Ancestor) title元素的先辈是 book元素和bookstore元素
2. 基本使用
2.1 工具安装
安装参考网站
https://blog.csdn.net/qq_31082427/article/details/84987723
查找某个特定的节点或者包含某个指定的值的节点
2.2 模块的使用
在Python中,我们安装lxml库来使用XPath 技术,lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取HTML/XML数据利用etree.HTML,将字符串转化为Element对象,lxml 可以自动修正 html 代码。
lxml python 官方文档:http://lxml.de/index.html
可使用 pip 安装:pip install lxml
使用 from lxml import etree
这个etree类能做什么?
# import lxml
from lxml import etree
# 第一个是将html/xml字符串转化为element对象
# 第二个是element对象可以转换为字符串或者是二进制类型的数据
wb_data = """
<div>
<ul>
<li class="item-0"><a href="link1.html">first 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">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
"""
html_element = etree.HTML(wb_data)
# print(html_element)
result = etree.tostring(html_element)
r = result.decode()
# print(type(r),r)
# 获取li标签下面a标签的href
links = html_element.xpath('//li/a/@href')
print(links)
# 获取li标签下a标签的内容
result = html_element.xpath('//li/a/text()')
print(result)
# 我想把这些数据组合到一个字典当中 例如{'href':'link1.html','title':'first item'}
for link in links:
d = {}
d['href'] = link
# 拿到下标索引值 (links.index(link)
d['title'] = result[links.index(link)]
print(d)
3. 豆瓣电影榜单爬取
需求:爬取电影的名字 评分 引言 详情页的url,每一页都爬取并且把数据保存到csv文件当中
import requests
from lxml import etree
import csv
# 网页分析
# https://movie.douban.com/top250?start=25&filter= 第二页
# https://movie.douban.com/top250?start=50&filter= 第三页
# https://movie.douban.com/top250?start=75&filter= 第四页
# (page-1)* 25
doubanUrl = 'https://movie.douban.com/top250?start={}&filter='
# 第一步获取网页源码
def getSource(url):
# 反爬 填写headers请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
response = requests.get(url,headers=headers)
# 防止出现乱码
response.encoding = 'utf-8'
# print(response.text)
return response.text
# 第二步定义一个函数 获取电影信息
def getEveryItem(source):
html_element = etree.HTML(source)
movieItemList = html_element.xpath('//div[@class="info"]')
# 定义一个空的列表
movieList = []
for eachMoive in movieItemList:
# 创建一个字典 像列表中存储数据[{电影一},{电影二}......]
movieDict = {}
title = eachMoive.xpath('div[@class="hd"]/a/span[@class="title"]/text()') # 标题
otherTitle = eachMoive.xpath('div[@class="hd"]/a/span[@class="other"]/text()') # 副标题
link = eachMoive.xpath('div[@class="hd"]/a/@href')[0] # url
star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()')[0] # 评分
quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()') # 引言(名句)
if quote:
quote = quote[0]
else:
quote = ''
# 保存数据
movieDict['title'] = ''.join(title+otherTitle)
movieDict['url'] = link
movieDict['star'] = star
movieDict['quote'] = quote
movieList.append(movieDict)
print(movieList)
return movieList
# 保存数据
def writeData(movieList):
with open('douban.csv','w',encoding='utf-8',newline='') as f:
writer = csv.DictWriter(f,fieldnames=['title','star','quote','url'])
writer.writeheader() # 写入表头
for each in movieList:
writer.writerow(each)
if __name__ == '__main__':
movieList = []
# 一共有10页
for i in range(10):
pageLink = doubanUrl.format(i * 25)
source = getSource(pageLink)
movieList += getEveryItem(source)
writeData(movieList)