• requests-html库轻体验-HTMLSession下载表情包


    requests-html实战,HTMLSession下载斗图啦最新表情包

    前言

    在这篇文章之前,我写了requests入门实践02_下载斗图拉最新表情包用正则表达式提取url,来下载斗图啦最新表情包,前几天我去查看时,直接就翻车了,代码根本提取不到表情包的URL咯,昨天意外看到一个视频,想到了直接用html解析库来改造(没错2020年7月我才想到用html解析库来处理响应, 这博主是真的菜).

    依赖库

    该脚本文件使用了:requests库, requests-html库, loguru库(可选,如果不需要,你得把文件中logger/loguru相关的内容给干掉)

    安装方法: pip install requests requests-html loguru

    requests-html

    官方文档:

    https://requests.readthedocs.io/projects/requests-html/en/latest/

    https://cncert.github.io/requests-html-doc-cn/#/

    全面支持解析JavaScript!
    CSS 选择器 (jQuery风格, 感谢PyQuery).
    XPath 选择器, for the faint at heart.
    自定义user-agent (就像一个真正的web浏览器).
    自动追踪重定向.
    连接池与cookie持久化.
    令人欣喜的请求体验,魔法般的解析页面.

    • 该脚本用的方法概览:

      from requests_html import HTMLSession
      # 相当于requests.Session(),它会自动记录并在所有请求之间持久保存cookie
      session = HTMLSession()
      # 请求方法,参数与requests一致
      res = session.get(url='http://www.baidu.com/')
      # 提取响应的html文件中所有的超链接(相对路径提取):注意只能提取到 <a herf="提取到这里的链接">
      res.html.links
      # 绝对url路径提取
      res.html.absolute_links
      # 通过css查找指定元素,(这需要一点css基础???)
      about = res.html.find('#about', first=True) # 解析:从响应的html文件中,查找ID为about的元素,first=True只返回第一个,first=False返回所有,返回值是一个list
      
      # 通过xpath查找指定元素,返回一个list (这就需要xpath基础了)
      res.html.xpath("//div[contains(@class,'page-content')]//a//img/@data-original") # 解析:// - html根目录,div[contains(@class, 'page-content')] - class为contains的div元素,下面的 class为page-content的元素, //a//img - 元素下的a标签下的img标签 , /@data-original - 属性为data-original的值
      
      # 通过查找到的element元素,得到下方所有的属性与值,返回形式是dict
      about.attrs
      

    脚本一览

    # 安装:pip install requests (必须)
    # 安装:pip install requests-html (必须)
    # 安装:pip install loguru (可选)
    # HTMLSession 同步会话
    import time
    
    from requests_html import HTMLSession
    # 创建文件目录
    import os
    
    # 日志库
    from loguru import logger
    
    """
    为避免下载重复图片,请选择注释掉文中不需要的文件名称处理方法,也可任意组合下载方法,文件名称处理方法
    """
    
    
    class Dowanlod_Image(object):
        def __init__(self, save_path='./img/'):
            """
    
            :param save_path: 文件保存目录,默认当前目录下新建img文件夹
            """
            self.save_path = save_path
            # 日志存放位置
            logger.add(f"file_{time.time()}.log")
    
            # 创建目录存放文件
            os.makedirs(save_path, exist_ok=True)
            logger.info(f'{save_path.split("/")[-1]}文件夹创建成功.')
            # 同步会话实例
            self.session = HTMLSession()
            self.headers = {
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) '
                              'Chrome/84.0.4147.89 Safari/537.36',
            }
            logger.info(f'session已实例化:{self.session}.')
    
        @logger.catch
        def main(self, start_page: int = 1, end_page: int = 2):
            """
    
            :param start_page: 默认参数,从第x页开始下载
            :param end_page: 默认参数,下载第y页之前的
            :return:
            """
            for index in range(start_page, end_page):
                # 访问斗图啦最新表情第index页
                base_url = f'https://www.doutula.com/photo/list/?page={index}'
                res = self.session.get(url=base_url, headers=self.headers)
                logger.info(f'请求{base_url}后得到的响应html{res.text}.')
                # 含links方法只能获取 a herf标签
                # print(res.html.absolute_links, '
    ', type(res.html.absolute_links))
    
                # 图片url 提取 :方法1
                # 选取element对象-css查找,first=True,只返回第一个,False返回所有
                img_element = res.html.find('.page-content .col-xs-6 img', first=False)
                logger.info(f'通过css查找.page-content .col-xs-6 img,得到的所有element对象.')
    
                # 图片url 提取: 方法2
                # xpath 直接提取出图片的链接,列表形式返回
                img_url_list = res.html.xpath("//div[contains(@class,'page-content')]//a//img/@data-original")
                logger.info(f'通过xpath查找到img标签中data-original属性的值,也就是我们需要的图片url.')
    
                # 文件名称处理:适配图片url提取-方法1
                for data in img_element:
                    # attrs返回element对象所有的属性字典
                    # 图片实际url
                    img_url = data.attrs.get('data-original')
                    # 文件后缀名
                    img_suffix = img_url.split('.')[-1]
                    # 完整文件名
                    img_name = data.attrs.get('alt').join(['', f'.{img_suffix}'])
                    # 文件名称处理,不能包含: / : * ? " < > |
                    wor_list = ['\', '/', ':', '*', '?', '"', '<', '>', '|']
                    for wor in wor_list:
                        if wor in img_name:
                            img_name = img_name.replace(wor, '_')
                    # print(img_url, img_name)
                    self.req_download(img_url, img_name)
    
                    
                # 文件名称处理:适配图片url提取-方法2: 这种方法整体简洁,但是没有中文文件名
                for img_url in img_url_list:
                    img_name = img_url.split('/')[-1]
                    # print(img_url, img_name)
                    self.ute_download(img_url, img_name)
    
        def ute_download(self, img_url, img_name):
            # 下载图片方法1:全适配
            from urllib.request import urlretrieve
            # 传入url, 文件保存路径
            urlretrieve(img_url, f'./{self.save_path}{img_name}')
            logger.info(f'{img_name}下载完成.')
    
        def req_download(self, img_url, img_name):
            # 下载图片方法2:全适配
            # 需单独请求图片url接口
            rep = self.session.get(img_url, headers=self.headers)
            with open(f'{self.save_path}{img_name}', 'wb') as f:
                # 写入二进制文件
                f.write(rep.content)
            logger.info(f'{img_name}下载完成.')
    
    
    if __name__ == '__main__':
        start_time = time.time()
        d_img = Dowanlod_Image()
        d_img.main(2, 3)
        end_time = time.time()
        run_time = end_time - start_time
        logger.debug("=====================")
        logger.info(f'运行耗时{run_time}.')
    
    

    实际结果

    Snipaste_2020-07-25_12-06-48.png

    代码Gitee库地址

    https://gitee.com/zy7y/study_packages.git

    参考资料

    https://www.cnblogs.com/-wenli/p/10160351.html
    https://requests.readthedocs.io/projects/requests-html/en/latest/
    https://cncert.github.io/requests-html-doc-cn/#/?id=element类

    作者:zy7y
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    典型用户和场景总结
    排球的详细记分规则
    js 实现全选
    博客搬家啦!
    leetcode #980 不同路径||| (java)
    ADV-299 宰羊 (java,过了30%)
    ADV-292 计算行列式 java
    ADV-302 秘密行动 java
    ADV-297 快速排序 java
    ADV-298 和谐宿舍2 动态规划
  • 原文地址:https://www.cnblogs.com/zy7y/p/13376228.html
Copyright © 2020-2023  润新知