zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    第一次离职了
    华为手机 关于Android真机调试的时候logcat中无法输出调试信息的解决办法
    ListView的简单实用
    博客生涯开始
    hdu1151:Air Raid(最小路径覆盖)
    hdu1151:Air Raid(最小路径覆盖)
    hdu1162:Eddy's picture(最小生成树)
    hdu1162:Eddy's picture(最小生成树)
    hdu1301:Jungle Roads(最小生成树)
    hdu1301:Jungle Roads(最小生成树)
  • 原文地址:https://www.cnblogs.com/zy09/p/14073729.html
Copyright © 2011-2022 走看看