1、etree示例引入:lxml是第三方库需要安装:pip install lxml -i https://pypi.douban.com/simple/
from lxml import etree
# 构造一个etree的HTML节点对象(可供Xpath解析)
html = etree.HTML(text)
# 读取text文本内容进行构造节点对象
html = etree.parse('./test.html', etree.HTMLParser())
2、提取页面下所有结点
result = html.xpath('//* ')
3、提取子节点
# 查找ul标签下的a标签
result = html.xpath('//ul//a')
# 查找ul标签的子节点是a的标签
result = html.xpath('//ul/a')
4、提取父节点:(查找父节点可以使用..来实现也可以使用parent::来获取父节点)
# 查找li标签属性为item-1的父节点
result = html.xpath('//li[@class="item-1"]/..') # 方法1
result = html.xpath('//li[@class="item-1"]/parent::*') # 方法2
# 提取li节点中role属性为menuitem的节点的父节点的name属性内容
result = html.xpath('//li[@class="item-1"]/../@name')
5、属性匹配
# 查找li标签的属性为item-1的标签
result = html.xpath('//li[@class="item-1"]')
6、提取文本内容
# 查找li的标签属性为class="item-0"的子孙节点里的文本
result = html.xpath('//li[@class="item-1"]//text()')
# 查找li的标签属性为class="item-0"的直接子节点里a标签下的文本
result = html.xpath('//li[@class="item-1"]/a/text()')
7、属性值获取
# 查找子孙结点为li标签下的子节点,为a的标签的属性,为href的值打印出来
result = html.xpath('//li/a/@href')
8、属性多值匹配 contains(@属性名, "属性部分值")
#匹配li标签属性,值是li的标签下的子标签为a下,输出文本
# result = html.xpath('//li[@class="li"]/a/text()')
# result = html.xpath('//li[@class="li li-first"]/a/text()')
# 在子孙节点的li标签里的,属性值里 包含 li的标签下的,子节点a标签下的文本
result = html.xpath('//li[contains(@class, "li")]/a/text()')
9、多属性匹配
运算符介绍:
运算符功能or或and与mod除余|返回节点集合+加法-减法*乘法=等于!=不等于< 小于<=小于或等于> 大于>=大于或等于# 满足 li标签属性值包含li和name值等于item的标签,同时满足
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
# 满足 li标签属性包含li又包含li-first
result = html.xpath('//li[contains(@class, "li") and contains(@class, "li-first")]/a/text()')
10、按序选择,通过索引的方式进行选择
# [数字]表示符合条件的第一个
result = html.xpath('//li[1]/a/text()')
# last() 表示位置是最后一个的
result = html.xpath('//li[last()]/a/text()')
# position表示位置小于3的
result = html.xpath('//li[position()<3]/a/text()')
# 表示位置减2的
result = html.xpath('//li[last()-2]/a/text()')
11、结点轴选择
节点轴选择轴功能ancestor选取当前节点的所有祖先节点ancestor-or-self选取当前结点的所有祖先结点以及当前结点本身attribute选取当前节点的所有属性值child选取当前节点的所有直接子节点descendant选取当前节点的所有后代元素descendant-or-self选取当前结点的所有子孙以及结点本身following选取文档中当前节点的结束标签之后的所有结点following-sibling选取当前节点的所有同级节点namespace选取当前结点的所有命名空间结点parent选取当前结点的父节点preceding选取文档中当前结点的开始标签之前的所有结点preceding-sbibling选取当前结点之前的所有同级结点self选取当前结点# 查找第一个li标签的父类中的div标签打印输出,返回一个列表
result = html.xpath('//li[1]/ancestor::div')
print(result)
# 查找第一个li标签的所有属性信息
result = html.xpath('//li[1]/attribute::*')
print(result)
#查找第一个li标签的所有子元素中,属性为href,其值为link1.html的a标签
result = html.xpath('//li[1]/child::a[@href="link1.html"]')
print(result)
#查找第一个li标签的所有后代中的span标签及其以下的数据打印输出
result = html.xpath('//li[1]/descendant::span')
print(result)
#查找第一个li标签结束后的所有,同级标签和同级以下标签,将其打印输出
result = html.xpath('//li[1]/following::*')
print(result)
# 查找第一个li标签结束后的所有同级标签将其打印输出
result = html.xpath('//li[1]/following-sibling::*')
print(result)
12. 用Xpath解析爬取豆瓣top250
### 用Xpath解析爬取豆瓣top250
from lxml import etree
import requests, json
def get_page(url):
'''
获取url网页代码
:param url: 要爬取的网址
:return: 网页代码
'''
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
print('get page success...')
return response.text
else:
exit('get page fail...')
def parse_page(text):
'''
解析豆瓣电影top250网页代码
:param html: 网页代码
:return: data需要爬取的数据
'''
html = etree.HTML(text)
items = html.xpath('//ol[@class="grid_view"]/li/div[@class="item"]')
for item in items:
#print(item.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()')[0])
yield {
'img': item.xpath('.//div[@class="pic"]//img/@src')[0],
'details': item.xpath('.//div[@class="hd"]/a/@href')[0],
'name': item.xpath('.//div[@class="hd"]//span[1]/text()')[0],
'director': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[0].split()[1],
'actor': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[0].split()[5] if len(item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[0].split())>5 else 'None',
'time': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[1].split()[0],
'nation': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[1].split()[2],
'type': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[1].split()[4:],
'score': item.xpath('.//div[@class="bd"]/div/span[@class="rating_num"]/text()')[0],
'introduction': item.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()') if item.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()') else 'None',
}
return items
def save_to_file(data):
'''
保存爬取到的数据到文本文件中
:param data:
:return:
'''
with open('豆瓣电影top250.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
def main(start):
url = 'https://movie.douban.com/top250?start=' + str(start)
text = get_page(url)
data = parse_page(text)
for item in data:
print(item)
save_to_file(item)
if __name__ == '__main__':
for i in range(10):
start = i * 25
main(start)