• 第14.7节 Python模拟浏览器访问实现http报文体压缩传输


    一、 引言
    在《第14.6节 Python模拟浏览器访问网页的实现代码》介绍了使用urllib包的request模块访问网页的方法。但上节特别说明http报文头Accept-Encoding最好不设置,否则服务端会根据该字段及服务端的情况采用对应方式压缩http报文体,如果爬虫应用没有解压支持会导致应用无法识别收到的响应报文体。本节简单介绍一下怎么处理响应报文体的压缩。
    在爬虫爬取网页时,如果在请求头中传递了“‘Accept-Encoding’:‘gzip’”信息则服务器会采用gzip压缩报文,此时客户端必须支持对报文解压缩才能识别报文。解gzip压缩需要安装gzip模块,并在服务器返回http应答报文时判断服务端是否压缩了报文,如果压缩了就进行解压处理,否则直接读取。

    二、 对HTTP响应报文的报文体支持压缩处理的爬虫处理步骤
    要进行响应HTTP报文体的压缩,爬虫应用需要进行如下处理:
    1、 在请求报文的http报文头中的Accept-Encoding中设置能支持的压缩格式;
    2、 读取响应报文后要判断响应报文头中的Content-Encoding的返回值的压缩格式;
    3、 调用对应的解压方法进行报文体解压。

    三、 案例
    1、 导入相关模块:
    import urllib.request
    from io import BytesIO
    import gzip

    2、 构造支持压缩的请求报文头
    本节在《第14.5节 利用浏览器获取的http信息构造Python网页访问的http请求头》的mkhead函数的基础上,增加一个参数来确认是否需要处理压缩报文,如果是则通过http报文头的Accept-Encoding参数向服务器告知支持的压缩格式,否则不设置压缩格式支持的请求报文头Accept-Encoding参数,代码如下:

      def mkhead(NeedEncoding=False):
        if NeedEncoding:
            header = {'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Encoding':'gzip',
            'Accept-Language':'zh-CN,zh;q=0.9',
            'Connection':'keep-alive',
            'Cookie':'uuid_tt_dd=10_35489889920-1563497330616-876822;......',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
        else:
            header = {'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Language':'zh-CN,zh;q=0.9',
            'Connection':'keep-alive',
            'Cookie':'uuid_tt_dd=10_35489889920-1563497330616-876822;......',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
            
        return header
    

    3、 读取响应报文后取响应报文头中的Content-Encoding的返回值的压缩格式

     req = urllib.request.Request(url=site,headers=header)
       sitersp = urllib.request.urlopen(req)
       Encoding = sitersp.info().get('Content-Encoding')  #取响应报文体的压缩格式
    

    4、 根据压缩对应情况进行处理后返回报文体的内容,如果是gzip压缩就调用gzip解压,如果未压缩就不进行解压处理,否则报错返回:

     if  Encoding== 'gzip':  #判断压缩格式是否gzip格式
            print(" Encoding== 'gzip'")
            buf = BytesIO(sitersp.read())
            fzip = gzip.GzipFile(fileobj=buf)
            return fzip.read().decode()
        elif not Encoding:  #是否没有压缩报文体
            print(" Encoding==None")
            return sitersp.read().decode()
        else:
            print(f"Content-Encoding={Encoding},can't unzip")
            return None
            
    

    四、 案例完整代码

    #读取压缩http响应报文
    import urllib.request
    from io import BytesIO
    import gzip
       
    def mkhead(NeedEncoding=False):
        if NeedEncoding:
            header = {'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Encoding':'gzip',
            'Accept-Language':'zh-CN,zh;q=0.9',
            'Connection':'keep-alive',
            'Cookie':'uuid_tt_dd=10_35489889920-1563497330616-876822;...... ',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
        else:
            header = {'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Language':'zh-CN,zh;q=0.9',
            'Connection':'keep-alive',
            'Cookie':'uuid_tt_dd=10_35489889920-1563497330616-876822;......',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
            
        return header 
    
    
    def readweb(site):
        header = mkhead(True)
        try:
            req = urllib.request.Request(url=site,headers=header)
            sitersp = urllib.request.urlopen(req)
        except Exception as e:
            print(e)
            return None
        Encoding = sitersp.info().get('Content-Encoding')
        if  Encoding== 'gzip':
            print(" Encoding== 'gzip'")
            buf = BytesIO(sitersp.read())
            fzip = gzip.GzipFile(fileobj=buf)
            return fzip.read().decode()
        elif not Encoding:
            print(" Encoding==None")
            return sitersp.read().decode()
        else:
            print(f"Content-Encoding={Encoding},can't unzip")
            return None
    
           
    readweb(r'https://blog.csdn.net/LaoYuanPython/article/details/100585881 ')[0:100]
    

    执行结果:

    >>> readweb(r'https://blog.csdn.net/LaoYuanPython/article/details/100585881 ')[0:100]
     Encoding== 'gzip'
    '<!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <link rel="canonical" href'
    >>>
    

    注意:代码中的cookie设置可以不要,那就是匿名爬取网页,如果需要非匿名则需要根据自己浏览器的cookie来设置。

    本节介绍了使用urllib包的request模块读取网页并支持解压的实现过程,以支持网页内容的压缩传输。

    老猿Python,跟老猿学Python!
    博客地址:https://blog.csdn.net/LaoYuanPython

    老猿Python博客文章目录:https://blog.csdn.net/LaoYuanPython/article/details/98245036
    请大家多多支持,点赞、评论和加关注!谢谢!

  • 相关阅读:
    结语
    创建ejs模板的express工程
    浏览器控制台命令调试——console
    JS获取URL中参数值(QueryString)的4种方法分享
    oracle之报错:ORA-00054: 资源正忙,要求指定 NOWAIT
    javascript 获取页面的高度及滚动条的位置的代码
    javascript 页面各种高度宽度
    导出Excel之Epplus使用教程2(样式设置)
    索引 'GXHRCS.PK_A253' 或这类索引的分区处于不可用状态
    数据库操作
  • 原文地址:https://www.cnblogs.com/LaoYuanPython/p/13643577.html
Copyright © 2020-2023  润新知