博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
爬虫 requests 模块
阅读量:5891 次
发布时间:2019-06-19

本文共 15497 字,大约阅读时间需要 51 分钟。

requests 模块

介绍

使用requests可以模拟浏览器的请求,

比起之前用到的urllib,requests模块的api更加便捷(本质就是封装了urllib3)

ps:

requests库发送请求将网页内容下载下来以后,并不会执行js代码,这需要我们自己分析目标站点然后发起新的request请求

下载安装

pip3 install requests

基本用法

常用的就是 requests.get() 和 requests.post()

>>> import requests>>> r = requests.get('https://api.github.com/events')>>> r = requests.post('http://httpbin.org/post', data = {
'key':'value'})>>> r = requests.put('http://httpbin.org/put', data = {
'key':'value'})>>> r = requests.delete('http://httpbin.org/delete')>>> r = requests.head('http://httpbin.org/get')>>> r = requests.options('http://httpbin.org/get')

GET请求

HTTP默认的请求方法就是GET

  • 没有请求体
  • 数据必须在1K之内!
  • GET请求数据会暴露在浏览器的地址栏中

常用的操作:

  • 在浏览器的地址栏中直接给出URL,那么就一定是GET请求
  • 点击页面上的超链接也一定是GET请求
  • 提交表单时,表单默认使用GET请求,但可以设置为POST

POST请求

  • 数据不会出现在地址栏中
  • 数据的大小没有上限
  • 有请求体
  • 请求体中如果存在中文,会使用URL编码

ps

  requests.post()用法与requests.get()完全一致

  特殊的是requests.post()有一个data参数,用来存放请求体数据

基于GET请求

用于对需求网页信息的发起。爬取数据时需要注意请求头携带,以及特殊,不常见请求头的携带。

否则无法正确爬取数据

基本请求

import requestsresponse=requests.get('http:/www.baidu.com/')print(response.text)

可选参数

params 查询参数

比如请求的地址为 

https://www.baidu.com/s?wd=python&pn=1

如果参数固定直接静态拼接即可

#在请求头内将自己伪装成浏览器,否则百度不会正常返回页面内容import requestsresponse=requests.get('https://www.baidu.com/s?wd=python&pn=1',                      headers={                        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',                      })print(response.text)

如果查询关键词是中文或者有其他特殊符号,则不得不进行url编码

from urllib.parse import urlencodewb = "haiyan海燕"encode_res = urlencode({
"k":wb},encoding="utf-8")print(encode_res) #k=haiyan%E6%B5%B7%E7%87%95keywords = encode_res.split("=")[1] #haiyan%E6%B5%B7%E7%87%95url = "https://www.baidu.com/s?wd=%s&pn=1"%(keywords)# url = "https://www.baidu.com/s?"+encode_resprint(url)# 然后拼接成urlresponse = requests.get( url, headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36", })

params参数的使用,等效于上面的实现效果,更加层次化,清晰

from urllib.parse import urlencodewd='海燕nnn'pn=1response=requests.get('https://www.baidu.com/',                      params={                          'wd':wd,                          'pn':pn                      },                      headers={                        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',                      })res2=response.text

auth 参数

 

 

cookies 参数

#登录github,然后从浏览器中获取cookies,以后就可以直接拿着cookie登录了,无需输入用户名密码import requestsCookies={
'user_session':'wGMHFJKgDcmRIVvcA14_Wrt_3xaUyJNsBnPbYzEL6L0bHcfc',}response=requests.get('https://github.com/settings/emails', cookies=Cookies) #github对请求头没有什么限制,我们无需定制user-agent,对于其他网站可能还需要定制print('378533872@qq.com' in response.text) #True

 基于POST请求

通常用于数据的提交操作,比如登陆信息提交,form数据操作等

用法类似于 request.get 参数会多一个 data 里面存放提交数据

主要需要的注意点是 session 以及 csrf token  的问题,否则无法正确爬取数据

POST 示例

1、对于登录来说,应该输错用户名或密码然后分析抓包流程

2、要做登录的时候一定记得要把cookie先清除

3、requests.session():中间的cookie都不用自己分析了,有用的没用的都给放进来了

4、response.cookie.get_dict()    #获取cookie

import requestsimport timefrom hashlib import md5import random# url F12 -> translate_o -> posturl = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'# headersheaders = {    'Cookie': 'OUTFOX_SEARCH_USER_ID=952038275@106.2.43.13; _ntes_nnid=39bac6d54f4e5647863eee31bd8619a5,1552811211160; OUTFOX_SEARCH_USER_ID_NCOO=131079768.4231536; JSESSIONID=aaaXEaw94d2zVbzXu9TPw; ___rl__test__cookies=1556623400788',    'Referer': 'http://fanyi.youdao.com/',    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'}proxies = {
'http': 'http://125.32.177.235:8080'}# Input wordkey = input('Input word:')# saltsalt = str(int(time.time() * 1000)) + str(random.randint(0, 10))# signstring = "fanyideskweb" + key + salt + "@6f#X3=cCuncYssPsuRUE"s = md5()s.update(string.encode())sign = s.hexdigest()# tsts = str(int(time.time() * 1000))# Form Datadata = { 'i': key, 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'salt': salt, 'sign': sign, 'ts': ts, 'bv': 'cf156b581152bd0b259b90070b1120e6', 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web', 'action': 'FY_BY_REALTlME'}res = requests.post( url, data=data, # proxies=proxies, headers=headers)res.encoding = 'utf-8'print(res.text)
模拟发送数据进行有道翻译 (post 数据处理)
'''一 目标站点分析    浏览器输入https://github.com/login    然后输入错误的账号密码,抓包    发现登录行为是post提交到:https://github.com/session    而且请求头包含cookie    而且请求体包含:        commit:Sign in        utf8:✓        authenticity_token:lbI8IJCwGslZS8qJPnof5e7ZkCoSoMn6jmDTsL1r/m06NLyIbw7vCrpwrFAPzHMep3Tmf/TSJVoXWrvDZaVwxQ==        login:egonlin        password:123二 流程分析    先GET:https://github.com/login拿到初始cookie与authenticity_token    返回POST:https://github.com/session, 带上初始cookie,带上请求体(authenticity_token,用户名,密码等)    最后拿到登录cookie    ps:如果密码时密文形式,则可以先输错账号,输对密码,然后到浏览器中拿到加密后的密码,github的密码是明文'''import requestsimport re#第一次请求r1=requests.get('https://github.com/login')r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授权)authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #从页面中拿到CSRF TOKEN#第二次请求:带着初始cookie和TOKEN发送POST请求给登录页面,带上账号密码data={    'commit':'Sign in',    'utf8':'✓',    'authenticity_token':authenticity_token,    'login':'317828332@qq.com',    'password':'alex3714'}r2=requests.post('https://github.com/session',             data=data,             cookies=r1_cookie             )login_cookie=r2.cookies.get_dict()#第三次请求:以后的登录,拿着login_cookie就可以,比如访问一些个人配置r3=requests.get('https://github.com/settings/emails',                cookies=login_cookie)print('317828332@qq.com' in r3.text) #True
自动登录github(自己处理 cookie 信息)
整合登陆 GitHub 应用

补充说明编码问题

requests.post(url='xxxxxxxx',              data={
'xxx':'yyy'}) # 没有指定请求头 # 默认的请求头:application/x-www-form-urlencoed# 如果我们自定义请求头是application/json,并且用data传值, 则服务端取不到值requests.post(url='', data={
'':1,}, headers={ 'content-type':'application/json' })requests.post(url='', json={
'':1,}, ) # 默认的请求头:application/json

session 的使用

示例: 登录 github

import requestsimport resession=requests.session()#第一次请求r1=session.get('https://github.com/login')authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #从页面中拿到CSRF TOKEN#第二次请求data={    'commit':'Sign in',    'utf8':'✓',    'authenticity_token':authenticity_token,    'login':'745xxx10@qq.com',    'password':'yangtuo'}r2=session.post('https://github.com/session',             data=data,             )#第三次请求r3=session.get('https://github.com/settings/emails')print('317828332@qq.com' in r3.text) # True

示例: 人人登录

import requests# 把用户名和密码信息post到一个URLpost_url = 'http://www.renren.com/PLogin.do' # 键为input标签中name的值post_data = {    'email' : '136xxxx09',    'password' : 'zhaxxxxx001'} headers = {    'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36',    'Referer' : 'http://www.renren.com/'} # 实例化session对象session = requests.session()session.post(post_url,data=post_data,headers=headers) # 访问个人主页URL地址url = 'http://www.renren.com/967469305/profile'res = session.get(url,headers=headers)print(res.text)

响应Response

通过 get 或 post 方式发出请求后,拿到的响应对象进行的一系列操作

属性

import requestsrespone=requests.get('http://www.jianshu.com')# respone属性print(respone.text)    # 全部内容print(respone.content) # bytesprint(respone.status_code)print(respone.headers) # 请求头 print(respone.cookies) # cookieprint(respone.cookies.get_dict())print(respone.cookies.items())print(respone.url) # 实际 url 地址print(respone.history) # 访问历史print(respone.encoding) # 字符编码#关闭:response.close()from contextlib import closingwith closing(requests.get('xxx',stream=True)) as response:    for line in response.iter_content():    pass

编码问题

.encoding="" 

import requestsresponse=requests.get('http://www.autohome.com/news')# response.encoding='gbk' #汽车之家网站返回的页面内容为gb2312编码的,而requests的默认编码为ISO-8859-1,如果不设置成gbk则中文乱码print(response.text)

响应数据分片

过大的响应体一次保存下来不太合理

比如下载视频时,如果视频100G,用response.content然后一下子写到文件中是不合理的

import requestsresponse=requests.get('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1509868306530&di=712e4ef3ab258b36e9f4b48e85a81c9d&imgtype=0&src=http%3A%2F%2Fc.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F11385343fbf2b211e1fb58a1c08065380dd78e0c.jpg')with open('a.jpg','wb') as f:    f.write(response.content)

stream参数: 一点一点的取,

steam=True , .iter_content()

import requestsresponse=requests.get('https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo-transcode/1767502_56ec685f9c7ec542eeaf6eac93a65dc7_6fe25cd1347c_3.mp4',                      stream=True)with open('b.mp4','wb') as f:    for line in response.iter_content():        f.write(line)

解析json

import requestsresponse=requests.get('http://httpbin.org/get')import jsonres1=json.loads(response.text) # 太麻烦 res2=response.json() # 直接获取json数据print(res1 == res2) #True

跳转和历史

By default Requests will perform location redirection for all verbs except HEAD.We can use the history property of the Response object to track redirection.The Response.history list contains the Response objects that were created in order to complete the request. The list is sorted from the oldest to the most recent response.For example, GitHub redirects all HTTP requests to HTTPS:>>> r = requests.get('http://github.com')>>> r.url'https://github.com/'>>> r.status_code>>> r.history[
]If you're using GET, OPTIONS, POST, PUT, PATCH or DELETE, you can disable redirection handling with the allow_redirects parameter:>>> r = requests.get('http://github.com', allow_redirects=False)>>> r.status_code>>> r.history[]If you're using HEAD, you can enable redirection as well:>>> r = requests.head('http://github.com', allow_redirects=True)>>> r.url'https://github.com/'>>> r.history[
]
官方示例 对于 HTTP 跳转 HTTPS 的示例演示

默认为 True ,表示响应数据为跳转后的页面,设置为 False 为跳转前的页面

allow_redirects=False

import requestsimport re#第一次请求r1=requests.get('https://github.com/login')r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授权)authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #从页面中拿到CSRF TOKEN#第二次请求:带着初始cookie和TOKEN发送POST请求给登录页面,带上账号密码data={    'commit':'Sign in',    'utf8':'✓',    'authenticity_token':authenticity_token,    'login':'317828332@qq.com',    'password':'alex3714'}#测试一:没有指定allow_redirects=False,则响应头中出现Location就跳转到新页面,r2代表新页面的responser2=requests.post('https://github.com/session',             data=data,             cookies=r1_cookie             )print(r2.status_code) #200print(r2.url) #看到的是跳转后的页面print(r2.history) #看到的是跳转前的responseprint(r2.history[0].text) #看到的是跳转前的response.text#测试二:指定allow_redirects=False,则响应头中即便出现Location也不会跳转到新页面,r2代表的仍然是老页面的responser2=requests.post('https://github.com/session',             data=data,             cookies=r1_cookie,             allow_redirects=False             )print(r2.status_code) #302print(r2.url) #看到的是跳转前的页面https://github.com/sessionprint(r2.history) #[]

高级用法

使用代理

#官网链接: http://docs.python-requests.org/en/master/user/advanced/#proxies#代理设置:先发送请求给代理,然后由代理帮忙发送(封ip是常见的事情)import requestsproxies={    'http':'http://egon:123@localhost:9743',#带用户名密码的代理,@符号前是用户名与密码    'http':'http://localhost:9743',    'https':'https://localhost:9743',}respone=requests.get('https://www.12306.cn',                     proxies=proxies)print(respone.status_code)#支持socks代理,安装:pip install requests[socks]cimport requestsproxies = {    'http': 'socks5://user:pass@host:port',    'https': 'socks5://user:pass@host:port'}respone=requests.get('https://www.12306.cn',                     proxies=proxies)print(respone.status_code)
import requestsimport randomurl = 'http://httpbin.org/get'headers = {    'User-Agent': 'Mozilla/5.0'}p_list = [    '79.138.99.254:8080',    '125.32.177.235:8080']ip_port = random.choice(p_list)ip = ip_port.split(":")[0]port = ip_port.split(":")[1]pro = {    'http': 'http://%s:%s' % (ip, port),    'https': 'https://localhost:9743',}try:    respone = requests.get(        url=url,        proxies=pro,        headers=headers)    respone.encoding = 'utf-8'    print(respone.text)except Exception as e:    print("代理ip异常")
代理演示demo

超时设置

#两种超时:float or tuple#timeout=0.1 #代表接收数据的超时时间#timeout=(0.1,0.2)#0.1代表链接超时  0.2代表接收数据的超时时间import requestsrespone=requests.get('https://www.baidu.com',                     timeout=0.0001)

认证设置

比如家里路由器的 admin 登陆页面。

#官网链接:http://docs.python-requests.org/en/master/user/authentication/#认证设置:登陆网站是,弹出一个框,要求你输入用户名密码(与alter很类似),此时是无法获取html的# 但本质原理是拼接成请求头发送#         r.headers['Authorization'] = _basic_auth_str(self.username, self.password)# 一般的网站都不用默认的加密方式,都是自己写# 那么我们就需要按照网站的加密方式,自己写一个类似于_basic_auth_str的方法# 得到加密字符串后添加到请求头#         r.headers['Authorization'] =func('.....')#看一看默认的加密方式吧,通常网站都不会用默认的加密设置import requestsfrom requests.auth import HTTPBasicAuthr=requests.get('xxx',auth=HTTPBasicAuth('user','password'))print(r.status_code)#HTTPBasicAuth可以简写为如下格式import requestsr=requests.get('xxx',auth=('user','password'))print(r.status_code)

上传文件

import requestsfiles={
'file':open('a.jpg','rb')}respone=requests.post('http://httpbin.org/post',files=files)print(respone.status_code)

异常处理

import requestsfrom requests.exceptions import * # 可以查看requests.exceptions获取异常类型try:    r=requests.get('http://www.baidu.com',timeout=0.00001)except ReadTimeout:    print('===:')# except ConnectionError: # 网络不通#     print('-----')# except Timeout:#     print('aaaaa')except RequestException:    print('Error')

证书

SSL Cert Verification 

#证书验证(大部分网站都是https)import requestsrespone=requests.get('https://www.12306.cn') #如果是ssl请求,首先检查证书是否合法,不合法则报错,程序终端#改进1:去掉报错,但是会报警告import requestsrespone=requests.get('https://www.12306.cn',verify=False) #不验证证书,报警告,返回200print(respone.status_code)#改进2:去掉报错,并且去掉警报信息import requestsfrom requests.packages import urllib3urllib3.disable_warnings() #关闭警告respone=requests.get('https://www.12306.cn',verify=False)print(respone.status_code)#改进3:加上证书#很多网站都是https,但是不用证书也可以访问,大多数情况都是可以携带也可以不携带证书#知乎\百度等都是可带可不带#有硬性要求的,则必须带,比如对于定向的用户,拿到证书后才有权限访问某个特定网站import requestsrespone=requests.get('https://www.12306.cn',                     cert=('/path/server.crt',                           '/path/key'))print(respone.status_code)

示例

import requestsfrom urllib.parse import urlencode# 请求方式kwords = input("请输入关键字:>>").strip()res = urlencode({
"wd":kwords}) # # 请求的url,当你在百度输入中文的时候,你把url拿下来会变成下面的这样格式的url,所以得urlencode一下url ="https://www.baidu.com/s?"+res #https://www.baidu.com/s?wd=%E5%9B%BE%E7%89%87response = requests.get( # 请求的url,当你在百度输入中文的时候,你把url拿下来会变成下面的这样格式的url url, # 请求头 headers={ "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36", },)with open("a.html","w",encoding="utf-8") as f: f.write(response.text)# print(response.status_code)
简单示例1  
kwords = input("请输入关键字:>>").strip()response = requests.get(    "https://www.baidu.com/s?",    # 请求的url,当你在百度输入中文的时候,你把url拿下来会变成下面的这样格式的url    params={        "wd":kwords,        'pn':20    },    # 请求头    headers={        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",    },)with open("b.html","w",encoding="utf-8") as f:    f.write(response.text)# print(response.status_code)
简单示例2

 

转载于:https://www.cnblogs.com/shijieli/p/10357094.html

你可能感兴趣的文章
Some tips about crawling large external data with bcs connector
查看>>
RHCE学习<1>RHEL6系统安装、安装VM Tools和配置YUM本地源
查看>>
Web Client Software Factory系列(2):Composite Web应用程序块
查看>>
Exchange Server 2007系列之二:管理工具简介
查看>>
Exchange server 2010系列教程之三 发送邮件测试
查看>>
java:自定义数据库连接池
查看>>
WPF的消息机制(三)- WPF内部的5个窗口之处理激活和关闭的消息窗口以及系统资源通知窗口...
查看>>
Linux资料收集贴(Vi命令集,Linux命令集)
查看>>
git 对比两个commit 之间的差异
查看>>
DDD 应对具体业务场景,Domain Model 重新设计
查看>>
SQL Server 存储字符数较大字段的问题
查看>>
FullText Search
查看>>
服务器备份攻略
查看>>
也做SQL查询:班级总成绩 前三名,总成绩有相等的情况
查看>>
NeHe OpenGL教程 第四十课:绳子的模拟
查看>>
ajax:数据传输方式简介
查看>>
FluentData-新型轻量级ORM 利用T4模板 批量生成多文件 实体和业务逻辑 代码
查看>>
begineer2
查看>>
Oracle免客户端For .Net(只为用NewLife.XCode开发Oracle的同学服务)
查看>>
NVelocity标签设置缓存的解决方案
查看>>