xpath

1.简介

XPath是一门在XML和HTML文档中查找信息的语言,可以用来在XML和HTML文档中对元素和属性进行遍历

XPath的安装

Chrome插件XPath Helper

点Chrome浏览器右上角:更多工具-----扩展程序-----谷歌商店--------勾选XPath Helper(需要翻墙)

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)
原文地址:https://www.cnblogs.com/zy09/p/14073729.html