xpath解析
xpath解析:最常用且最便捷高效的一种解析方式。通用性。
1、xpath解析原理:
1.实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获。
2、环境的安装:
pip install lxml
3、如何实例化一etree对象:from lxml import entree
-
1.将本地的html文档中的源码数据加载到etree对象中:
etree.parse(filrPath)
-
2.可以将从互联网上获取的源码数据加载到该对象中
etree.HTML('page_text')
-
xpath('Xpath表达式') #返回的是列表
4.xpath表达式
-
/ :表示的是从根节点开始定位。表示的是一个层级。
例如:test.html中的根节点是html
#定位到title标签 r=tree.xpath('/html/head/title') #从根节点开始一层一层去定位,返回的列表,返回的是element对象,不是具体内容 print(r) #输出是列表 ''' 输出:[<Element title at 0x26ed87de2c0>] ''' #有几个div,返回列表中就有几个Element r = tree.xpath('/html/body/div') # 从根节点开始一层一层去定位,返回的列表,返回的是element对象,不是具体内容 print(r) ''' 输出:[<Element div at 0x2041d1ee400>, <Element div at 0x2041d1ee480>, <Element div at 0x2041d1ee4c0>] '''
-
//:表示的是多个层级。可以表示从任意位置开始定位。
#有几个div,返回列表中就有几个Element r = tree.xpath('//div') # 同 print(r)
-
属性定位://div[@class=‘song’] tag[@attrName=“attrValue”]
div[@class='song'] tag[@attrName="attrValue"] #例子 #属性定位 r = tree.xpath('//div[@class="song"]') #[]中括号@是固定格式,返回的是列表 #返回的是[<Element div at 0x2af276df340>]
-
索引定位://div[@class=“song”]/p[3] 索引是从1开始的。
# 索引定位 r = tree.xpath('//div[@class="song"]/p[3]') # []中索引是从1开始的 print(r) #[<Element p at 0x29af6930180>]
-
取文本:
-
/text() 获取的是标签中直系的文本内容
# 定位 r = tree.xpath('//div[@class="tang"]/ul/li[5]/a/text()') # []中索引是从1开始的 print(r) #['杜牧'] r = tree.xpath('//div[@class="tang"]/ul/li[5]/a/text()')[0] #杜牧
-
//text() 标签中非直系的文本内容(所有的文本内容)
# 取文本 //text() r = tree.xpath('//div[@class="tang"]/ul/li[5]//text()') # []中索引是从1开始的 print(r) #['杜牧']
-
-
取属性:
/@attrName ==>img/src# 取属性 /@attrName r = tree.xpath('//div[@class="song"]/img/@src') # @src :@属性 /@attrName print(r) #['http://www.baidu.com/meinv.jpg'] r = tree.xpath('//div[@class="song"]/img/@src')[0] #http://www.baidu.com/meinv.jpg
5、xpath实战:58二手房
import requests
from lxml import etree
if __name__=="__main__":
headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
url='https://zz.58.com/ershoufang/'
page_text=requests.get(url=url,headers=headers).text
#print(page_text)
#数据解析
tree=etree.HTML(page_text)
#r1与r相同
#r1=tree.xpath('//section[@class="list"]/div/a/div[@class="property-content"]/div[@class="property-content-detail"]/div[@class="property-content-title"]/h3/text()')
r = tree.xpath('//div[@class="property-content-title"]/h3/text()')
print(r)
#print(r1)
6、xpath解析案例-4k图片解析下载
-
如果文字乱码的话:
-
#方法一 #先获取网页的HTML #page=requests.get(url=url,headers=headers).text #乱码了 respone=requests.get(url=url,headers=headers) #手动设定解决乱码 respone.encoding="utf-8" #乱码没解决 page=respone.text
-
#方法二 # 通用处理中文乱码的解决方案 img_name=img_name.encode('iso-8859-1').decode('gbk') #print(img_name)
-
#需求:解析下载图片数据 http://pic.netbian.com/4kmeinv/
import requests
from lxml import etree
import os
if __name__=="__main__":
#创建一个新文件夹
if not os.path.exists('tupian'):
os.mkdir('tupian')
headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
url='https://pic.netbian.com/4kmeinv/'
#先获取网页的HTML
#page=requests.get(url=url,headers=headers).text #乱码了
respone=requests.get(url=url,headers=headers)
#手动设定解决乱码
#respone.encoding="utf-8" #乱码没解决
page=respone.text
#数据解析
tree=etree.HTML(page)
li_list=tree.xpath('//div[@class="slist"]/ul/li')
#print(li_list)
for li in li_list:
img_src='https://pic.netbian.com'+li.xpath('./a/img/@src')[0]
#print(img_src)
img_name=li.xpath('./a/img/@alt')[0]+'.jpg'
# 通用处理中文乱码的解决方案
img_name=img_name.encode('iso-8859-1').decode('gbk')
#print(img_name)
#进行持久化存储
img_data=requests.get(url=img_src,headers=headers).content #二进制数据
#图片路径
img_path='tupian/'+img_name
with open(img_path,'wb') as fp:
fp.write(img_data)
print(img_name,'下载成功!!!')
# with open(img_path,'wb') as fp:
# fp.write(img_data)
# print(img_name,"下载成功!!")
7、解析出所有城市名称
#项目需求:解析出所有城市名称https://www.aqistudy.cn/historydata/
import requests
import os
from lxml import etree
if __name__=="__main__":
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
url='https://www.aqistudy.cn/historydata/'
page_text=requests.get(url=url,headers=headers).text
#数据解析
tree=etree.HTML(page_text)
all_city_names = []
#解析热门
hot_list=tree.xpath('//div[@class="hot"]/div[@class="bottom"]/ul/li')
for li in hot_list:
hot_name=li.xpath('./a/text()')[0]
all_city_names.append(hot_name)
name_list=tree.xpath('//div[@class="all"]/div[@class="bottom"]/ul/div[2]/li')
#host_name_list=tree.xpath('./a/text()')
#print(name_list)
#解析所有城市
for li in name_list:
host_city_name=li.xpath('./a/text()')[0]
#print(host_city_name)
all_city_names.append(host_city_name)
print(all_city_names,len(all_city_names))
#项目需求:解析出所有城市名称https://www.aqistudy.cn/historydata/
import requests
import os
from lxml import etree
if __name__=="__main__":
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
url='https://www.aqistudy.cn/historydata/'
page_text=requests.get(url=url,headers=headers).text
#数据解析
tree = etree.HTML(page_text)
# 解析到热门城市和所有城市对应的a标签
# //div[@class="hot"]/div[@class="bottom"]/ul/li 热门城市a标签的层级关系
# //div[@class="all"]/div[@class="bottom"]/ul/div[2]/li 全部城市a标签的层级关系
#包括热门城市和全部城市
a_list=tree.xpath('//div[@class="all"]/div[@class="bottom"]/ul/div[2]/li | //div[@class="hot"]/div[@class="bottom"]/ul/li ')
all_city_names = []
for a in a_list:
city_name=a.xpath('./a/text()')[0]
all_city_names.append(city_name)
print(all_city_names, len(all_city_names))
8、作业
-
注意post请求和get请求
-
# 进行持久化存储 二进制数据进行存储 #data=requests.get(url=page3_url,headers=headers) #这里是post请求,get不可以 data1=requests.post(url=page3_url,headers=headers) data2=data1.content
#作业:爬取站长素材中免费简历模板 https://sc.chinaz.com/
# https://sc.chinaz.com/jianli/free.html
# 压缩包也是二进制
import requests
from lxml import etree
import os
if __name__=="__main__":
if not os.path.exists('yasuobao'):
os.mkdir('yasuobao')
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
url='https://sc.chinaz.com/jianli/free.html'
page=requests.get(url=url,headers=headers).text
#解析数据
tree=etree.HTML(page)
li_list=tree.xpath('//div[@class="sc_warp mt20"]/div/div/div')
#print(li_list)
for li in li_list:
post_url='https:'+li.xpath('./a/@href')[0]
#print(post_url)
#进入某一简历的网页
#page1=requests.get(url=post_url,headers=headers).text
# 手动设定解决乱码
# response.encoding="utf-8" #乱码没解决
response=requests.get(url=post_url,headers=headers)
response.encoding = "utf-8"
page1= response.text
#解析
tree1=etree.HTML(page1)
page2=tree1.xpath('//div[@class="down_wrap"]/div[2]/ul/li[1]')
for lin in page2:
#提取出压缩包下载链接,不加[0],就在列表
page3_url=lin.xpath('./a/@href')[0]
#print(page3_url)
page3_name=lin.xpath('//div[@class="ppt_tit clearfix"]/h1/text()')[0] +'.rar'
#文字乱码没有解决,换上一种
#page3_name = page3_name.encode('iso-8859-1').decode('gbk')
# print(page3_name)
# 进行持久化存储 二进制数据进行存储
#data=requests.get(url=page3_url,headers=headers)
#这里是post请求,get不可以
data1=requests.post(url=page3_url,headers=headers)
data2=data1.content
#压缩包路径
page3_path='yasuobao/'+page3_name
#print(page3_path)
with open(page3_path,mode='wb') as fp:
fp.write(data2)
print(page3_name,"下载完成!!!")