技术学习:Python(十四)|爬虫篇|爬虫请求库

活动地址:CSDN21天学习挑战赛

🏮1 前言

学习Python还是得跟着老师学习,请参考老师博文

🎈1.1 简介

Python 内置了 requests 模块,该模块主要用来发 送 HTTP 请求,requests 模块比 urllib 模块更简洁。requests是使用Apache2 licensed 许可证的HTTP库。Request支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的URL和POST数据自动编码。在python内置模块的基础上进行了高度的封装,从而使得python进行网络请求时,变得人性化,使用Requests可以轻而易举的完成浏览器可有的任何操作。当然,requests模块国际化,友好。requests会自动实现持久连接keep-alive。

上面写了一大堆,简单总结来说,如下:

  • 简洁
  • 支持HTTP连接和连接池,自动实现长连接
  • 支持cookie
  • 支持文件上传
  • 支持响应内容的编码
  • 支持国际化
  • 🎈1.2 安装

    从以前学习的,可以知道这个库很容易安装,在Mac下,打开终端,如下:

    # 查看已经安装的库
    Aion.Liu $ pip list
    Package    Version
    ---------- -------
    meson      0.63.0
    pip        22.2.2
    protobuf   4.21.4
    pymongo    4.2.0
    PyMySQL    1.0.2
    pypi       2.1
    setuptools 63.2.0
    xlrd       2.0.1
    xlwt       1.3.0
    xmltodict  0.13.0
    
    # 安装requests库
    Aion.Liu $ pip install requests
    Collecting requests
      Using cached requests-2.28.1-py3-none-any.whl (62 kB)
    Collecting certifi>=2017.4.17
      Downloading certifi-2022.6.15-py3-none-any.whl (160 kB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 160.2/160.2 kB 360.7 kB/s eta 0:00:00
    Collecting idna<4,>=2.5
      Downloading idna-3.3-py3-none-any.whl (61 kB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 61.2/61.2 kB 160.3 kB/s eta 0:00:00
    Collecting charset-normalizer<3,>=2
      Downloading charset_normalizer-2.1.0-py3-none-any.whl (39 kB)
    Collecting urllib3<1.27,>=1.21.1
      Downloading urllib3-1.26.11-py2.py3-none-any.whl (139 kB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 139.9/139.9 kB 69.9 kB/s eta 0:00:00
    Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests
    Successfully installed certifi-2022.6.15 charset-normalizer-2.1.0 idna-3.3 requests-2.28.1 urllib3-1.26.11
    

    现在,我们已经安装了requests模块,下面开始更详细的了解他。

    🏮2 requests模块详操

    🎈2.1 resquests属性和方法

    属性和方法 备注
    delete(url, args) 发送 DELETE 请求到指定 url
    get(url, params, args) 发送 GET 请求到指定 url
    head(url, args) 发送 HEAD 请求到指定 url
    patch(url, data, args) 发送 PATCH 请求到指定 url
    post(url, data, json, args) 发送 POST 请求到指定 url
    put(url, data, args) 发送 PUT 请求到指定 url
    request(method, url, args) 向指定的 url 发送指定的请求方法

    🎈2.2 response属性和方法

    属性和方法 备注
    apparent_encoding 编码方式
    close() 关闭与服务器的连接
    response.content 返回响应的内容,字节(byte)为单位的数据
    response.text 返回响应的内容,字符串unicode 类型数据
    response.content.decode 解决中文乱码,默认utf-8,其他的编码类型gbkgb2312asciiso-8859-1
    cookies 返回一个 CookieJar 对象,包含了从服务器发回的 cookie
    elapsed 返回一个 timedelta 对象,包含了从发送请求到响应到达之间经过的时间量,可以用于测试响应速度。比如 r.elapsed.microseconds 表示响应到达需要多少微秒。
    encoding 解码 r.text 的编码方式
    headers 返回响应头,字典格式
    history 返回包含请求历史的响应对象列表(url)
    is_permanent_redirect 如果响应是永久重定向的 url,则返回 True,否则返回 False
    is_redirect 如果响应被重定向,则返回 True,否则返回 False
    iter_content() 迭代响应
    iter_lines() 迭代响应的行
    json() 返回结果的 JSON 对象 (结果需要以 JSON 格式编写的,否则会引发错误)
    links 返回响应的解析头链接
    next 返回重定向链中下一个请求的 PreparedRequest 对象
    ok 检查 “status_code” 的值,如果小于400,则返回 True,如果不小于 400,则返回 False
    raise_for_status() 如果发生错误,方法返回一个 HTTPError 对象
    reason 响应状态的描述,比如 “Not Found” 或 “OK”
    request 返回请求此响应的请求对象
    status_code 返回 http 的状态码,比如 404 和 200(200 是 OK,404 是 Not Found)
    url 返回响应的 URL

    简单实验下,如下:

    # 导入库,引入依赖
    >>> import requests
    >>>
    >>> url = "http://www.baidu.com"
    >>>
    >>> response = requests.get(url)
    # 获取请求
    >>> print(response)
    <Response [200]>
    # 请求返回值的类型
    >>> print(type(response))
    <class 'requests.models.Response'>
    # 请求返回值的响应编码
    >>> print(response.status_code)
    200
    # 请求返回值内容类型
    >>> print(type(response.text))
    <class 'str'>
    # 请求返回值的cookies
    >>> print(response.cookies)
    <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
    # 请求返回值的文本内容
    >>> print(response.text)
    <!DOCTYPE html>
    <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç™¾åº¦ä¸€ä¸‹ï¼Œä½ å°±çŸ¥é“</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>æ–°é—»</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>å
    ³äºŽç™¾åº¦</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前å¿
    读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
    >>>> print(response.content)
    b'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\xa5\xe9\x81\x93</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>\xe6\x96\xb0\xe9\x97\xbb</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>\xe5\x9c\xb0\xe5\x9b\xbe</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>\xe8\xa7\x86\xe9\xa2\x91</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>\xe8\xb4\xb4\xe5\x90\xa7</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>\xe7\x99\xbb\xe5\xbd\x95</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">\xe7\x99\xbb\xe5\xbd\x95</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">\xe6\x9b\xb4\xe5\xa4\x9a\xe4\xba\xa7\xe5\x93\x81</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>\xe5\x85\xb3\xe4\xba\x8e\xe7\x99\xbe\xe5\xba\xa6</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>\xe4\xbd\xbf\xe7\x94\xa8\xe7\x99\xbe\xe5\xba\xa6\xe5\x89\x8d\xe5\xbf\x85\xe8\xaf\xbb</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>\xe6\x84\x8f\xe8\xa7\x81\xe5\x8f\x8d\xe9\xa6\x88</a>&nbsp;\xe4\xba\xacICP\xe8\xaf\x81030173\xe5\x8f\xb7&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n'
    

    有些属性没有罗列出来,可以实验性的测试下。

    🎈2.3 GET请求|发送带headers参数请求

  • 1)查看浏览器请求头部信息

    打开百度,然后使用快捷键F12打开,或者任意一个网页任意处右键打开检查。

  • 2)依次打开网络(Network)==> 名称(Name) ==> 标头(Headers) ==> User-Agent

  • 可以看到这里的User-Agent

    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
    
  • 3)实验代码
  • headers接收字典类型的参数作为请求头,请求头部字段作为key,字段对应的值作为value。具体的实验代码如下:

    >>> import requests
    # 目标网址
    >>> url = "http://www.baidu.com/"
    
    # 构建请求头字典,最重要的就是User-Agent
    # 如果需要其他请求头,就在headers字典中加上
    >>> headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
    
    # 发送请求获取响应
    >>> response = requests.get(url,headers=headers)
    >>> print(response.text)
    

    🎈2.4 GET请求|发送带参数的请求

  • 删除网页多余的参数,简化搜索
  • 首先按照老师博文 查看百度的搜索内容。实验图片就不发了,可以按照博文操作一遍就可以。我们想要搜索关键字python,最终看到的结果差不多。两个搜索url如下:

    第一个URLhttps://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=python&fenlei=256&rsv_pq=89208a3e00138578&rsv_t=b2celG4Qr%2BQGonWg7J8W9l4SEpOAyY08gnYSr7klPqQ1ykbhQ3%2FYUwVccyfC&rqlang=en&rsv_enter=1&rsv_dl=tb&rsv_sug3=7&rsv_sug1=5&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&prefixsug=python&rsp=5&inputT=1230&rsv_sug4=1817&rsv_sug=1

    第二个URLhttps://www.baidu.com/s?word=python

  • 方式一:网页带参数
  • >>> import requests
    # 目标网址
    >>> url = "https://www.baidu.com/s?wd=python"
    >>> headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
    # 发送请求获取响应
    >>> response = requests.get(url,headers=headers)
    >>> print(response.text)
    
  • 方式二:通过params构造参数字典
  • >>> import requests
    # 目标网址
    >>> url = "https://www.baidu.com/s?"
    >>> headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
    # 请求参数是一个字典
    >>> kw = {'wd': 'python'}
    # 发送请求的时候设置参数字典,获取响应
    >>> response = requests.get(url, headers=headers, params=kw)
    >>> print(response.text)
    

    🎈2.5 发送带参数的请求|携带cookie

    首先找到cookie,找到cookie的步骤如下,网络 ==> 名称 ==> 请求标头,找到Cookie,这个便是要找到的值。

    题外,我在这里发现一个问题,就是在载荷中,查询字符串参数的hisdata中的fq的值是3,其实前面我请求了2次了,这里可以猜测下,是请求的历史数据或缓存数据,应该从搜索引擎优化这个角度来解析。

    实验代码如下:

    >>> headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
        'Cookie': 'PSTM=1652800193; BD_UPN=123253; BIDUPSID=B6DECB8DEA9B7780AD0CAF744C59CD0E; BAIDUID=52BD4BA13A939B8909AF3868433505C8:SL=0:NR=10:FG=1; BD_HOME=1; H_PS_PSSID=36560_36755_36641_37107_36413_36955_36917_36569_36779_37078_37134_37055_26350_22157_37022; BA_HECTOR=2l2k2l2004ak052k84a5qgrs1hfh9bv17; BAIDUID_BFESS=52BD4BA13A939B8909AF3868433505C8:SL=0:NR=10:FG=1; ZFY=yBSQpVTPoIjIZS2wQABxq9vbmOlwhxBgoIv2mTEnodI:C; delPer=0; BD_CK_SAM=1; PSINO=7; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; B64_BOT=1; baikeVisitId=9de7055f-ca35-464f-95a4-28c2e347e2eb; COOKIE_SESSION=99_0_5_5_2_6_0_0_5_5_1_0_198_0_0_0_1660462670_0_1660466598%7C7%230_0_1660466598%7C1; H_PS_645EC=62ebmN0nyfgetgvl2QP%2FN153uwXQAO3OlMRWkXOhpJKCGjt4Ug9FtOTOGzg'
    }
    

    🎈2.6 超时参数timeout

    背景
    请求很久没有结果,网页一直在Loading,在爬虫中,这个就降低了我们的效率。这个时候我们需要对请求进行强制要求,让请求在特定的时间内返回结果,否则报错。

    import requests
    
    # 目标网址
    >>> url = "https://www.baidu.com/"
    >>> headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
    }
    >>> try:
    # 超时设置为10秒
    >>>     response = requests.get(url, headers=headers, timeout=10)  
    >>> except:
    >>>     for i in range(4):  # 循环去请求网站
    >>>         response = requests.get(url, headers=headers, timeout=20)
    >>>         if response.status_code == 200:
    >>>             break
    >>> html_str = response.text
    

    备注:r = requests.get('url',timeout=1) #设置秒数超时,仅对于连接有效。

    🎈2.7 代理参数proxies

    首先看下具体的请求链路图,大体先理解下,根据老师博文整理如下图所示:

    实验代码如下:

    >>> proxies = {
        "http": "http://12.34.5679:9527",
        "https": "https://12.34.5679:9527",
        ……
    }
    >>> requests.get('url', proxies=proxies)
    

    🎈2.8 POST请求

    语法:requests.post(url, data={key: value}, json={key: value}, args)

  • url 请求 url。
  • data 参数为要发送到指定 url 的字典、元组列表、字节或文件对象。
  • json 参数为要发送到指定 url 的 JSON 对象。
  • args 为其他参数,比如 cookies、headers、verify等。
  • 实验代码如下:

    # 1、基本POST实例
    >>> import requests
    >>> payload = {'key1': 'value1', 'key2': 'value2'}
    >>> ret =requests.post("http://mobile.weather.com.cn/data/forecast/101010100.html", data=payload)
    >>> print(ret.text)
          
    # 2、发送请求头和数据实例  
    >>> import requests
    >>> import json 
    >>> url = 'http://mobile.weather.com.cn/data/forecast/101010100.html'
    >>> payload = {'some': 'data'}
    >>> headers = {'content-type': 'application/json'} 
    >>> ret = requests.post(url, data=json.dumps(payload), headers=headers)  
    >>> print(ret.text)
    >>> print(ret.cookies)
    

    🎈2.9 身份认证| HTTP Basic Auth

    常用的身份认证有很多,今日我打算补充下这个身份认证——基础身份认证(HTTP Basic Auth)。

    实验代码:

    >>> import requests
    >>> from requests.auth import HTTPBasicAuth
      
    >>> r = requests.get('https://httpbin.org/hidden-basic->>> auth/user/passwd', auth=HTTPBasicAuth('user', 'passwd'))
    # r = requests.get('https://httpbin.org/hidden-basic-auth/user/passwd', >>> auth=('user', 'passwd'))    # 简写
    >>> print(r.json())
    

    另一种非常流行的HTTP身份认证形式是摘要式身份认证,Requests对它的支持也是开箱即可用的:

    >>> requests.get(URL, auth=HTTPDigestAuth('user', 'pass')
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 技术学习:Python(十四)|爬虫篇|爬虫请求库

    发表评论