1.简介
XPath是一门在XML和HTML文档中查找信息的语言,可以用来在XML和HTML文档中对元素和属性进行遍历
XPath的安装
Chrome插件XPath Helper
点Chrome浏览器右上角:更多工具-----扩展程序-----谷歌商店--------勾选XPath Helper(需要FQ)
2.语法详解
- xpath表达式: - xpath('xpath表达式') - /:表示的是从根节点开始定位。表示的是一个层级。 - //:表示的是多个层级。可以表示从任意位置开始定位。 - 属性定位://div[@class='song'] tag[@attrName="attrValue"] - 索引定位://div[@class="song"]/p[3] 索引是从1开始的。 - 取文本: - /text() 获取的是标签中直系的文本内容 - //text() 标签中非直系的文本内容(所有的文本内容) - 取属性: /@attrName ==>img/src
#1.选取节点 ''' / 如果是在最前面,代表从根节点选取,否则选择某节点下的某个节点.只查询子一辈的节点 /html 查询到一个结果 /div 查询到0个结果,因为根节点以下只有一个html子节点 /html/body 查询到1个结果 // 查询所有子孙节点 //head/script //div . 选取当前节点 .. 选取当前节点的父节点 @ 选取属性 //div[@id] 选择所有带有id属性的div元素 <div id="sidebar" class="sidebar" data-lg-tj-track-code="index_navigation" data-lg-tj-track-type="1"> ''' #2.谓语 ''' 谓语是用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。 //body/div[1] body下的第一个div元素 //body/div[last()] body下的最后一个div元素 //body/div[position()<3] body下的位置小于3的元素 //div[@id] div下带id属性的元素 <div id="sidebar" class="sidebar" data-lg-tj-track-code="index_navigation" data-lg-tj-track-type="1"> //input[@id="serverTime"] input下id="serverTime"的元素 模糊匹配 //div[contains(@class,'f1')] div的class属性带有f1的 通配符 * //body/* body下面所有的元素 //div[@*] 只要有用属性的div元素 //div[@id='footer'] //div 带有id='footer'属性的div下的所有div元素 //div[@class='job_bt'] //dd[@class='job-advantage'] 运算符 //div[@class='job_detail'] and @id='job_tent' //book/title | //book/price 选取 book 元素的所有 title 和 price 元素。 也可以百度搜索XPath语法 .//a/text() 当前标签下所有a标签的文字内容 //tr[position()>1 and position()<11] 位置大于1小于11 ''' #需要注意的知识点 ''' 1./和//的区别:/代表子节点,//代表子孙节点,//用的比较多 2.contains有时候某个属性中包含了多个值,那么使用contains函数 //div[contains(@class,'lg')] 3.谓语中的下标是从1开始的,不是从0开始的 '''
3.要在python中使用xpath,要导入一个库 lxml。
这个是C编写的库,直接pip3 install lxml可能会有一些显示问题,但是不影响使用。
然而程序员特有的代码洁癖让我看见波浪线也不会爽,所以去https://www.lfd.uci.edu/~gohlke/pythonlibs/下载lxml的whl文件进行pip(根据自己的pycharm版本选择)
4.lxml和xpath的结合使用
# -*-coding:utf8 -*- from lxml import etree #1.获取所有tr标签 #2.获取第2个tr标签 #3.获取所有class等于even的标签 #4.获取所有a标签的href属性 #5.获取所有的职位信息(纯文本) parser=etree.HTMLParser(encoding='utf-8') html=etree.parse('tencent.html',parser=parser) #1.获取所有tr标签 #xpath函数返回的是一个列表 # trs=html.xpath('//tr') # print(trs) # for tr in trs: # print(etree.tostring(tr,encoding='utf-8').decode('utf-8')) #2.获取第2个tr标签 # trs=html.xpath('//tr[2]')[0] #这样直接找第2个tr标签,实际上会把所有的table下的第二个tr标签找出来, #为了更精准,可以先把table标签找到,再找这个table下的第二个tr标签 # trs=html.xpath('//table[@class="tablelist"]//tr[1]')[0] # print(etree.tostring(trs,encoding='utf-8').decode('utf-8')) #3.获取所有class等于even的标签 # trs=html.xpath("//tr[@class='even']") # for tr in trs: # print(etree.tostring(tr, encoding='utf-8').decode('utf-8')) #4.获取所有a标签的href属性 # a_list=html.xpath('//a/@href') # for a in a_list: # print(a) #5.获取所有的职位信息(纯文本) trs=html.xpath('//tr[position()>1 and position()<11]') positions=[] for tr in trs: #写了//后,则一定会从整个文档找a标签,会无视前面的tr # href=tr.xpath('//a') #写了.后,则获取当前标签下的a标签 href=tr.xpath('.//a/@href')[0] fullurl='http://hr.tencent.com/'+href #title文本信息不是td[1]的直接子元素标签,所以要加./td[1]//text() title=tr.xpath('./td[1]//text()')[0] category=tr.xpath('./td[2]/text()')[0] nums=tr.xpath('./td[3]/text()')[0] address=tr.xpath('./td[4]/text()')[0] pubtime=tr.xpath('./td[5]/text()')[0] position={ 'url':fullurl, 'title':title, 'category':category, 'nums':nums, 'pubtime':pubtime } positions.append(position) # print(positions) #6.获取纯文本信息还可以用string # print(html.xpath("string(//tr[1])")) # trs=html.xpath('//tr') # for tr in trs: # print(tr.xpath("string(.)").strip()
获取https://bing.ioliu.cn/ 必应壁纸并按照目录保存
#-*- coding:utf-8 -*- from bs4 import BeautifulSoup import requests from lxml import etree import re import os import time #定义 url,headers url = 'https://bing.ioliu.cn/' headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' } #定义request 会话对象 requestsSession = requests.Session() imgPage = (x for x in range(1,146)) #定义一个 页数生成器 #定义请求函数 def getImg(imgPage): for page in imgPage: #页数循环 params = { "p": page } #请求页面 responseHtml = requestsSession.get(url=url,headers=headers,params=params,timeout=3).text #通过etree 实例化,通过xpath 表达式过滤 src xpathObj = etree.HTML(responseHtml) imgSrc = xpathObj.xpath('//div[@class="container"]//div[@class="card progressive"]/img/@src') page =str(page) #以页数为目录,通过 os.path 判断下 if not os.path.exists('./Img/' + page): os.mkdir('./Img/' + page) #获取每个页面的 图片并且存储 for i in imgSrc: imgName = i.split('/')[-1].split('?')[0] imgData = requestsSession.get(url=i,headers=headers).content imgPath = './Img/' + page + '/' + imgName + '.jpg' with open(imgPath,'wb') as dp: dp.write(imgData) print(imgName, '下载成功!') # 每个页面请求间隔3s 防止被禁 time.sleep(3) if __name__ == "__main__": # ll = range(56,146) getImg(imgPage)