• day6-xpath解析+多线程


    xpath解析

    4.1 xpath语法

    1. xpath基本概念

      1)树:整个html(xml)代码结构就是一个树结构

      2)节点:树结构中的每一个元素(标签)就是一个节点

      3)根节点(根元素): html或者xml最外面的那个标签(元素)

      4)节点内容:标签内容

      5)节点属性:标签属性

    2. xml数据格式

    xml和json一样,是一种通用的数据格式(绝大部分编程语言都支持的数据格式)

    xml是通过标签(元素)的标签内容和标签属性来保存数据的。

    """
    示例:保存一个超市信息
    1)json数据
    {
        "name": "永辉超市",
        "address": "肖家河大厦",
        "staffs":[
            {"name":"小明", "id": "s001", "position": "收营员", "salary": 4000},
            {"name":"小花", "id": "s002", "position": "促销员", "salary": 3500},
            {"name":"张三", "id": "s003", "position": "保洁", "salary": 3000},
            {"name":"李四", "id": "s004", "position": "收营员", "salary": 4000},
            {"name":"王五", "id": "s005", "position": "售货员", "salary": 3800}
        ],
        "goodsList":[
            {"name": "泡面", "price": 3.5, "count": 120, "discount":0.9},
            {"name": "火腿肠", "price": 1.5, "count": 332, "discount":1},
            {"name": "矿泉水", "price": 2, "count": 549, "discount":1},
            {"name": "面包", "price": 5.5, "count": 29, "discount":0.85}
        ]
    }
    
    xml数据:
    
        
            
                小明
                收营员
                4000
            
            
                小花
                促销员
                3500
            
            
                张三
                保洁
                3000
            
            
                李四
                收营员
                4000
            
            
                王五
                售货员
                3800
            
        
    
        
            
                泡面
                3.5
                120
            
            
                火腿肠
                1.5
                332
            
            
                矿泉水
                2
                549
            
            
                面包
                5.5
                29
            
        
    
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    1. xpath语法

      1)创建树结构获取树的根节点

      etree.XML(xml数据)

      etree.HTML(html数据)

    f = open('files/data.xml', encoding='utf-8')
    root = etree.XML(f.read())
    f.close()
    
    • 1
    • 2
    • 3

    2)根据xpath获取指定标签

    节点对象.xpath(路径) - 返回路径对应的所有的标签,返回值是列表,列表中的元素是标签对象(节点

    对象)

    路径的写法:

    1. 绝对路径: 用"/"开头的路径 - /标签在树结构中的路径 (路径必须从根节点开始写)
    2. 相对路径: 路径开头用"."标签当前节点(xpath前面是谁,'.'就代表谁), "…"表示当前节点的上层节点
    3. 全路径: 用"//"开头的路径 - 在整个树中获取标签

    注意:绝对路径和全路径的写法以及查找方式和是用谁去点的xpath无关

    result = root.xpath('/supermarket/staffs/staff/name/text()')
    print(result)
    
    result = root.xpath('./staffs/staff/name/text()')
    print(result)
    
    staff1 = root.xpath('./staffs/staff')[0]  # 获取第一个员工对应的staff标签
    result = staff1.xpath('./name/text()')
    print(result)  # ['小明']
    
    result = staff1.xpath('../staff/name/text()')
    print(result)  # ['小明', '小花', '张三', '李四', '王五']
    
    result = root.xpath('//name/text()')
    print(result)
    
    result = staff1.xpath('//goods/name/text()')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3)获取标签内容

    节点对象.xpath(获取标签的路径/text()) - 获取指定路径下所有标签的标签内容

    result = root.xpath('//position/text()')
    print(result)
    
    • 1
    • 2

    4)获取标签属性值

    节点对象.xpath(获取标签的路径/@属性名)

    result = root.xpath('/supermarket/@name')
    print(result)  # ['永辉超市']
    
    result = root.xpath('//staff/@id')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5)谓语(条件)

    a. 位置相关谓语

    [N] - 第N个

    [last()] - 最后一个

    [last()-N]; [last()-1] - 倒数第2个 、 [last()-2] - 倒数第3个

    [position()>N]、[position()=N]、[position()<=N]

    result = root.xpath('//staff[1]/name/text()')
    print(result)  # ['小明']
    
    result = root.xpath('//staff[last()]/name/text()')
    print(result)  # ['王五']
    
    result = root.xpath('//staff[last()-1]/name/text()')
    print(result)  # ['李四']
    
    result = root.xpath('//staff[position()<3]/name/text()')
    print(result)  # ['小明', '小花']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    b.属性相关谓语

    [@属性名=属性值] - 指定属性是指定值的标签

    [@属性名] - 拥有指定属性的标签

    result = root.xpath('//staff[@class="c1"]/name/text()')
    print(result)
    
    result = root.xpath('//staff[@id="s003"]/name/text()')
    print(result)
    
    result = root.xpath('//goods[@discount]/name/text()')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    c.子标签内容相关谓语 - 根据子标签的内容来筛选标签

    [子标签名>数据]

    [子标签名<数据]

    [子标签名>=数据]

    [子标签名<=数据]

    [子标签名=数据]

    result = root.xpath('//goods[price=2]/name/text()')
    print(result)
    
    • 1
    • 2

    6)通配符 - 写路径的时候用*来表示所有标签或者所有属性

    result = root.xpath('//staff[1]/*/text()')
    print(result)
    
    # *[@class="c1"]  == .c1
    result = root.xpath('//*[@class="c1"]/name/text()')
    print(result)
    
    result = root.xpath('//goods[@*]/name/text()')
    print(result)
    
    result = root.xpath('/supermarket/@*')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7)若干路径 - |

    路径1|路径2 - 同时获取路径1和路径2的内容

    result = root.xpath('//goods/name/text()|//staff/position/text()')
    print(result)
    
    • 1
    • 2

    4.2 xpath解析豆瓣

    import requests
    from lxml import etree
    import csv
    def get_html():
        headers = {
            'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
        }
        url='https://movie.douban.com/top250'
        response = requests.get(url=url,headers=headers)
        return response.text
    
    def get_data(html:str):
        root = etree.HTML(html)
        name_list = root.xpath('//ol[@class="grid_view"]/li/div/div/div/a/span[1]/text()')
        # plot_list = root.xpath('//div[@class="bd"]/p/text()')
        comment_list = root.xpath('//span[@class="rating_num"]/text()')
        discourse_list = root.xpath('//span[@class="inq"]/text()')
        comment_count = root.xpath('//div[@class="star"]/span[4]/text()')
        all_data = list(map(lambda i1,i2,i3,i4:[i1,i2,i3,i4],name_list,comment_list,comment_count,discourse_list))
        with open('files/电影.csv','w',encoding='utf-8',newline='') as f:
            writer = csv.writer(f)
            writer.writerow(['电影名称','评分','评论数','简介'])
            writer.writerows(all_data)
    
    
    if __name__ == '__main__':
        data = get_html()
        get_data(data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    4.3 多线程

    1. 基本理论

    1)进程和线程

    进程: 一个正在运行的应用程序就是一个进程,每个进程均运行在其专门且受保护的内存空间中

    线程: 线程是进程执行任务的基本单元(一个进程中的任务都是在线程中执行的)

    进程就是车间,线程就是车间里面的工人。

    一个进程中默认有一个线程,这个线程叫主线程。

    2)线程的特点

    如果在一个线程中执行多个任务,任务是串行执行的。

    (当一个程序中有很多个任务的时候,如果只有一个线程,那么程序的执行效率会很低)

    3)多线程

    一个进程中有多个线程就是多线程。

    多线程执行任务的时候,多个任务可以同时(并行)执行。

    4)多线程原理

    一个cpu同一时间只能调度一个线程,多线程其实是cpu快速的在多个线程之间进行切换,造成多个线程

    同时执行的假象。

    (提高cpu利用率)

    1. Python使用多线程的方法

      一个进程默认只有一个线程,这个线程叫主线程,主线程以外的线程都叫子线程。

      Python程序中如果需要子线程,必须创建线程类(Thread)的对象。

    from threading import Thread
    from time import sleep
    from datetime import datetime
    
    
    def download(name):
        print(f'{name}开始下载:{datetime.now()}')
        sleep(2)
        print(f'{name}下载结束:{datetime.now()}')
    
    
    if __name__ == '__main__':
        # 情况1:在一个线程(主线程)中下载3个电影
        # download('肖生克救赎')
        # download('霸王别姬')
        # download('阿甘正传')
    
        # 情况2:使用3个子线程分别下载3个电影
        # 1)创建线程对象
        """
        线程对象 = Thread(target=函数, args=元组)
        a.函数  - 可以是普通函数函数名,也可以是匿名函数。这个函数就是需要子线程中执行的任务。
        b.元组  - 元组中的元素就是在子线程中调用target对应的函数的时候需要的参数
        """
        t1 = Thread(target=download, args=('肖生克救赎',))
        t2 = Thread(target=download, args=('霸王别姬',))
        t3 = Thread(target=download, args=('阿甘正传',))
    
        # 2)启动线程 - 让子线程调用对应的函数
        t1.start()
        t2.start()
        t3.start()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    4.4 多线程获取豆瓣电影

    import requests
    from lxml import etree
    from threading import Thread
    from datetime import datetime
    import csv
    
    def get_html(page):
        headers = {
            'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
        }
        url=f'https://movie.douban.com/top250?start={page}&filter='
        response = requests.get(url=url,headers=headers)
        get_data(response.text)
    
    def get_data(html:str):
        root = etree.HTML(html)
        name_list = root.xpath('//ol[@class="grid_view"]/li/div/div/div/a/span[1]/text()')
        # plot_list = root.xpath('//div[@class="bd"]/p/text()')
        comment_list = root.xpath('//span[@class="rating_num"]/text()')
        discourse_list = root.xpath('//span[@class="inq"]/text()')
        comment_count = root.xpath('//div[@class="star"]/span[4]/text()')
        all_data = list(map(lambda i1,i2,i3,i4:[i1,i2,i3,i4],name_list,comment_list,comment_count,discourse_list))
        print(all_data)
        print(f'下载完成:{datetime.now()}')
        with open('files/电影.csv','a',encoding='utf-8',newline='') as f:
            writer = csv.writer(f)
            writer.writerow(['电影名称','评分','评论数','简介'])
            writer.writerows(all_data)
    
    
    if __name__ == '__main__':
        for page in range(0,256,25):
            t = Thread(target=get_html,args=(page,))
            t.start()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    Spring Cloud Alibaba 分布式微服务高并发数据平台化(中台)思想+多租户saas设计的企业开发架构
    阿里云Hologres助力好未来网校实时数仓降本增效
    获取外网IP接口
    Git的使用之分支操作
    matlab,c,c++小区别记录笔记
    使用VSBT构建C和C++开源项目
    NET CORE Configuraion 使用详解
    从零入门 Vite 与 Webpack 对比
    ShiroFilter
    第7章 项目进阶,构建安全高效的企业服务(上)
  • 原文地址:https://blog.csdn.net/qq_59778168/article/details/126410463