爬虫—Requests高级用法

Requests高级用法

1.文件上传

  我们知道requests可以模拟提交一些数据。假如有的网站需要上传文件,我们也可以用requests来实现。

import requests

files = {'file': open('favicon.ico', 'rb')}
res = requests.post('http://httpbin.org/post', files=files)
print(res.text)

  上一篇博客中,我们保存了一个favicon.ico文件,这次用它来模拟文件上传的过程。favicon.ico文件需要和当前脚本在同一目录下,运行结果如下:

{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "data:application/octet-stream;base64,AAABAAIAEBAAAAEAIAAoBQAAJgAAACAgAAABACAAKBQAAE4FAAA......AAAAAAA="
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "6665", 
    "Content-Type": "multipart/form-data; boundary=f03eff231fa14cfbbd7ef2cd51bae3b6", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "json": null, 
  "origin": "183.129.61.15, 183.129.61.15", 
  "url": "https://httpbin.org/post"
}

  以上在files字段中省略了部分内容,这个网站会返回响应,里面包含files字段,而form字段为空,这说明文件上传会使用单独的字段来标识。

2.Cookies

  先用一个示例查看获取Cookies的过程:

# 获取Cookies
res = requests.get('http://www.baidu.com')
print(res.cookies)
for k, v in res.cookies.items():
    print(k + ":" + v)

  结果如下:

for .baidu.com/>]>
BDORZ:27315

  这里调用cookies属性即可获取到Cookies,可以发现它是一个RequestsCookieJar类型,使用items()方法将其转化为元祖组成的列表,遍历输出每一个Cookies的名称和值,实现Cookies的遍历解析。

  当然,我们也可以使用Cookies来维持登陆状态,下面以百度个人中心为例。首先登录百度个人中心,将Headers中的Cookies内容复制下来:

           爬虫—Requests高级用法_第1张图片

  可以替换成 你自己的Cookie,将其设置到Headers里面,然后在发送请求:

# 设置cookie,发送请求
headers = {
    'Cookie': 'BIDUPSID=EDBD62A1D608B5CDC72B06CA0C59680A; PSTM=1546959880; BDUSS=BCSHh3OVMtTW5XUnB6SEF4UFExUFhPRUc5Ty1sV'
              'FRkRERvRWZ3bE9sWlN2Y0ZjQVFBQJCQAAAAAAAAAAAEAAABW7900TGltaXTSwcrW1drM7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
              'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIwmlxSMJpcV3; MCITY=-340%3A; BAIDUID=5C140375092D783C088CEA7282B89772'
              ':FG=1; delPer=0; PSINO=5; BDRCVFR[bLbo9QmdyQn]=aeXf-1x8UdYcs; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; '
              'H_PS_PSSID=1427_21108_29064_28519_29099_28831_28585_22157; PHPSESSID=63vpocfpukn41u0h1nolsluq95; '
              'Hm_lvt_4010fd5075fcfe46a16ec4cb65e02f04=1558949858; Hm_lpvt_4010fd5075fcfe46a16ec4cb65e02f04=1558949858',
    'Host':'i.baidu.com'
}
res = requests.get('http://i.baidu.com/', headers=headers)
print(res.text)

  结果如下:




    "UTF-8">
    
    百度个人中心——您在百度的家
    "description" content="百度个人中心是百度用户管理个性化信息的平台,在这里,您可以体验贴吧的交流、知道的解答、百科的全面、空间的个性、云盘的强大……感受百度为您带来的方便、快捷与乐趣。">
    "keywords" content="个人中心,个人主页,个人帐号,个人空间">
    
    "shortcut icon" type="image/ico" href="http://www.baidu.com/favicon.ico" />
    "stylesheet" href="http://uc-vs.bdimg.com/v4/20181107x2/dep/font-awesome/4.0.3/less/font-awesome.css">
    
    "stylesheet" href="http://uc-vs.bdimg.com/v4/20181107x2/asset/home/css/main.css">

    
    
    "http://uc-vs.bdimg.com/v4/20181107x2/dep/respond/1.3.0/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />
    "http://i.baidu.com/static/respond/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />
    

    



class="result-op">
    
class="main-wrap">
'{"mod":"header"}'>
class="header-stackup" data-scroll-reveal="enter from the top over 0.66s">
class="ibx-container row clr"> "/" target="_self" class="header-logo header-logo-index">
class="header-tool header-tool-cal"> '{"act":"cal_click"}' href="/my/cal" class="header-tool-cal-link"> 日历 class="header-tool-cal-bg">
class="header-tc-content"> class="header-tc-ct-bg">
class="header-tool header-tool-news"> "/msg/messages/list/" class="header-tool-news-num">消息
class="header-tc-content"> class="header-tc-ct-bg">
class="news-header">数据加载中。。。
class="header-tool header-tool-ps"> "https://www.baidu.com" target="_blank"/>百度首页
"enter from the top over 0.66s" class="header-app ibx-container" data-click='{"mod":"header"}'>
class="ibx-container row">
class="row user-panel">
class="col span_5_1">
class="col span_5_4">
"ibx-cal" data-click='{"mod":"cal"}'>
class="ibx-inner" id="ibx-cal-content">
class="row card-panel" data-click='{"mod": "card_video"}'> class="rule-wrap">"video" name="video" class="rule">
class="col span_4_4">
class="ibx-even">
class="ibx-inner" id="ibx-mod-video">
class="row card-panel" data-click='{"mod": "card_nuomi"}'> class="rule-wrap">"nuomi" name="nuomi" class="rule">
class="col span_4_4">
class="ibx-even">
class="ibx-inner" id="ibx-mod-nuomi">
class="row card-panel" data-click='{"mod": "card_lvyou"}'> class="rule-wrap">"lvyou" name="lvyou" class="rule">
class="col span_4_4">
class="ibx-even">
class="ibx-inner" id="ibx-mod-lvyou">
class="row card-panel">
class="col span_4_2" data-click='{"mod": "card_zhidao"}'> class="rule-wrap">"zhidao" name="zhidao" class="rule">
class="ibx-odd">
"ibx-mod-zhidao" class="ibx-inner ibx-mod-zhidao">
class="col span_4_2" data-click='{"mod": "card_baifubao"}'> class="rule-wrap">"baifubao" name="baifubao" class="rule">
class="ibx-odd">
"ibx-mod-baifubao" class="ibx-inner ibx-mod-baifubao">
class="col span_4_2" data-click='{"mod": "card_koubei"}'> class="rule-wrap">"koubei" name="koubei" class="rule">
class="ibx-odd">
"ibx-mod-koubei" class="ibx-inner ibx-mod-koubei">
class="col span_4_2 OP_LOG_LINK" data-click='{"mod":"card_mgr","act":"msg_click"}'>
class="ibx-even editCard">
class="ibx-inner editCard-inner">
class="editCard-inner-add">
class="editCard-inner-tip">添加卡片
class="ibx-advice"> class="ibx-advice-logo" href="javascript:;">
class="ibx-advice-ctx">意见反馈
'{"mod":"card_mgr","act":"msg_click"}' class="ibx-manage"> class="ibx-manage-logo" href="javascript:;">
class="ibx-manage-ctx OP_LOG_OTHERS">卡片管理
class="back-to-top-wrap" data-click='{"mod":"back-to-top","act":"back-to-top-link"' > class="back-to-top" href="javascript:;">
class="ibx-card-manage" data-click='{"mod":"card_mgr"}'>
class="ibx-cm-mask">
class="ibx-cm-main">
class="ibx-cm-main-title clr">
class="ibx-cm-main-title-ctx">卡片管理
"javascript:;" class="ibx-cm-main-close" title="关闭">
class="ibx-cm-main-add">
class="ibx-cm-main-add-ctx"> class="ibx-cm-main-adding-ctx">可添加
    class="ibx-cmm-add-list">
  • class="ibx-cmm-add-item default"> 无可添加卡片
class="ibx-cm-main-added">
class="ibx-cm-main-add-ctx"> class="ibx-cm-main-added-ctx">已添加
    class="ibx-cmm-add-list">
  • '{"act":"set_video"}' class="ibx-cmm-add-item ibx-card-video" data-type="video">
  • '{"act":"set_nuomi"}' class="ibx-cmm-add-item ibx-card-nuomi" data-type="nuomi">
  • '{"act":"set_lvyou"}' class="ibx-cmm-add-item ibx-card-lvyou" data-type="lvyou">
  • '{"act":"set_zhidao"}' class="ibx-cmm-add-item ibx-card-zhidao" data-type="zhidao">
  • '{"act":"set_baifubao"}' class="ibx-cmm-add-item ibx-card-baifubao" data-type="baifubao">
  • '{"act":"set_koubei"}' class="ibx-cmm-add-item ibx-card-koubei" data-type="koubei">
  • class="ibx-cmm-add-item default"> 无已添加卡片
Process finished with exit code 0
View Code

  我们发现结果中包含了登录后页面显示内容,那么就证明登陆成功了。还有一种方法是构造RequestsCookieJar对象来设置cookie参数,相对繁琐,效果与上面的方法一样,就不多作介绍了。

3.会话维持

  在requests中,直接使用get()或post()方法确实可以做到模拟网页的请求,但是这实际上是两个不同的会话,相当于用了两个浏览器打开不同的页面。会话维持相当于打在原来的浏览器上新开了一个页面,这样就不用每次取设置cookies了——这就是Session对象。  

# Session对象
requests.get('http://httpbin.org/cookies/set/num/123456')
res = requests.get('http://httpbin.org/cookies')
print(res.text)

  这里我们请求了一个测试网站,设置了一个Cookie,名称为num,内容为123456,之后又发起了请求,获取Cookies。结果如下:

{
  "cookies": {}
}

  这样并不能获取到Cookies,我们再使用Session对象试试:

session = requests.Session()
session.get('http://httpbin.org/cookies/set/num/123456')
res = session.get('http://httpbin.org/cookies')
print(res.text)

  运行结果:

{
  "cookies": {
    "num": "123456"
  }
}

  获取成功!利用Session可以做到同一个会话不用担心Cookies问题,可以用于模拟登陆成功之后进行下一步的操作。

4.代理设置

  对于某些网站,在测试的时候请求几次,都能正常获取内容。一旦开始爬取,对于大规模的频繁请求,网站可能会弹出验证码,或者跳转到登陆认证,或者封禁IP,导致一定时间内无法访问。此时,就需要设置代理还解决这个问题,就要用到proxies参数。  

# 代理设置
proxies = {
    'http': 'http://10.10.1.10:3308',
    'https': 'https://10.10.1.10:1080'
}
requests.get('http://www.baidu.com', proxies=proxies)

  上面的代理肯定是无效的,可以更换有效代理再去尝试。

  如果需要使用到HTTP Basic Auth,可以使用类似:http://user:password@host:port这样的语法来设置。

# HTTP Basic Auth设置
proxies = {
    'http': 'http://user:[email protected]:3308',
}
requests.get('http://www.baidu.com', proxies=proxies)

  除了这些外,requests还支持socks协议的代理。需要先安装socks这个库

pip3 install requests[socks]

  示例如下:

# socks代理设置
proxies = {
    'http': 'socks5://user:[email protected]:3308',
}
requests.get('http://www.baidu.com', proxies=proxies)

5.超时设置

  我们也可以设置一个超时时间,即超过了这个时间还没有得到响应就报错。这就需要使用timeout参数了,这个时间计算是发出请求到服务器返回响应的时间。

# 超时设置
res = requests.get('http://www.baidu.com', timeout=1)
print(res.status_code)

  实际上,请求分为两个阶段,连接(connect)和读取(read),上面设置的timeout是二者的时间的总和。如果要分别指出,可以传入一个元祖。

res = requests.get('http://www.baidu.com', timeout=(5, 20))

  如果想永久等待,就可以直接设置timeout为None,或者不设置,默认是None。那么就永远不会返回超时错误。

6.身份认证

  在访问网站时,我们可能会遇到需要身份认证的页面,需要输入用户名和密码登录的页面。此时可以使用requests自带的身份认证功能。

# 身份认证
from requests.auth import HTTPBasicAuth

res = requests.get('http://www.baidu.com', auth=HTTPBasicAuth('username', 'password'))
print(res.status_code)

运行结果:
200

  当然,上面的代码可以直接简写成一个元祖。

res = requests.get('http://www.baidu.com', auth=('username', 'password'))

  如果用户名和密码都正确的话,就会成功,返回200状态码。否则返回401状态码。

7.Prepared Request

  将请求表示为数据结构,其中各个参数都可以通过一个Request对象来表示。这个数据结构就叫做Prepared Request。

# Prepared Request
from requests import Request, Session

url = 'http://httpbin.org/post'
data = {
    'name': 'rain'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
se = Session()
req = Request('POST', url, data=data, headers=headers)  # 构造Request对象
pre = se.prepare_request(req)                           # 转换成Prepared Request对象
res = se.send(pre)
print(res.text)

  这里引入了Request,然后使用url,data,headers参数构造了一个Request对象,之后需要再使用Session的prepared_request()方法将其转化为一个Prepared Request对象,最后调用send方法发送。

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "rain"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "9", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
  }, 
  "json": null, 
  "origin": "183.129.61.15, 183.129.61.15", 
  "url": "https://httpbin.org/post"
}

  这里可以看到from字段的值与我们data的值一致,这种方法同样达到了POST的请求效果。

  有了这个Request对象,可以把请求当作独立的对象来看待,这样在进行队列调度时就会非常方便。后面我们会用它来构造一个Request队列。

转载于:https://www.cnblogs.com/zivli/p/10932168.html

你可能感兴趣的:(爬虫—Requests高级用法)