03 requests retrying cookie

版权声明:内容版权为CSDN用户:kayseen 所有,若您需要引用、转载,需要注明来源及原文链接 https://blog.csdn.net/m0_43394876/article/details/89952876

1 使用requests处理cookie请求的三种方法

1.1回顾cookie和session的区别

  • cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗。
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。
  • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

1.2 爬虫中为什么要使用cookie

  • 带上cookie的好处
    • 能够访问登录后的页面
    • 正常的浏览器在请求服务器的时候肯定会带上cookie(第一次请求某个地址除外),所以对方服务器有可能会通过是否携带cookie来判断我们是否是一个爬虫,对应的能够起到一定的反爬的效果
  • 带上cookie的坏处
    • 一套cookie往往对应的是一个用户的信息,请求太频繁有更大的可能性被对方识别为爬虫
    • 那么上面的问题如何解决 ?使用多个账号

1.3 使用 session

session = requests.Session()
session.post(url,data) #cookie会存在session中
session.get(url) #会带上之前的cookie

  • requests 提供了一个叫做session类,来实现客户端和服务端的会话保持

  • 会话保持有两个内涵:

    • 保存cookie
    • 实现和服务端的长连接
  • 使用方法

      session = requests.session()
      response = session.get(url,headers)
    
    - 1 实例化对象
    - 2 session.get(url) #cookie保存在session中
    - 3 session.get(url) #带上保存在session中cookie
    

    session实例在请求了一个网站后,对方服务器设置在本地的cookie会保存在session中,下一次再使用session请求对方服务器的时候,会带上前一次的cookie

  • 动手:

    动手尝试使用session来登录人人网: http://www.renren.com/PLogin.do(先不考虑这个url地址从何而来),请求体的格式:{"email":"username", "password":"password"}

1.4 cookie放在headers中

了解headers中cookie

  • headers中的cookie:
    • 使用分号(;)隔开
    • 分号两边的类似a=b形式的表示一条cookie
    • a=b中,a表示键(name),b表示值(value)
    • 在headers中仅仅使用了cookie的name和value

由于headers中对cookie仅仅使用它的name和value,所以在代码中我们仅仅需要cookie的name和value即可

在headers中使用cookie

headers = {
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
"Cookie":" Pycharm-26c2d973=dbb9b300-2483-478f-9f5a-16ca4580177e; Hm_lvt_98b9d8c2fd6608d564bf2ac2ae642948=1512607763; Pycharm-26c2d974=f645329f-338e-486c-82c2-29e2a0205c74; _xsrf=2|d1a3d8ea|c5b07851cbce048bd5453846445de19d|1522379036"}

requests.get(url,headers=headers)

cookie有过期时间,所以直接复制浏览器中的cookie可能意味着下一程序继续运行的时候需要替换代码中的cookie,对应的我们也可以通过一个程序专门来获取cookie供其他程序使用;当然也有很多网站的cookie过期时间很长,这种情况下,直接复制cookie来使用更加简单

1.3 使用cookies参数

  • cookies的形式:字典
cookies = {"cookie的name":"cookie的value"}
  • 使用方法:
requests.get(url,headers=headers,cookies=cookie_dict)

2. requests模块获取cookie

requests.utils.dict_from_cookiejar : 把cookiejar对象转化为字典

import requests

url = "http://www.baidu.com"
response = requests.get(url)
print(type(response.cookies))

cookies = requests.utils.dict_from_cookiejar(response.cookies)
print(cookies)

输出为:

<class 'requests.cookies.RequestsCookieJar'>
{'BDORZ': '27315'}

寻找登录接口的方法

  • form表单action对应的url地址
    • 用户名和密码的input标签中,name的值作为键,用户名和密码作为值的字典,作为post data
  • 通过抓包,定位url地址
    • form data

3. requests处理证书错误

出现这个问题的原因是:ssl的证书不安全导致

在代码中请求如下:

import requests

url = "https://www.12306.cn/mormhweb/"
response = requests.get(url)

返回

ssl.CertificateError ...

为了在代码中能够正常的请求,我们修改添加一个参数

import requests

url = "https://www.12306.cn/mormhweb/"
response = requests.get(url,verify=False)

4. 超时参数的使用

在平时网上冲浪的过程中,我们经常会遇到网络波动,这个时候,一个请求等了很久可能任然没有结果

对应的,在爬虫中,一个请求很久没有结果,就会让整个项目的效率变得非常低,这个时候我们就需要对请求进行强制要求,让他必须在特定的时间内返回结果,否则就报错

使用方法如下:

response = requests.get(url,timeout=3)

通过添加timeout参数,能够保证在3秒钟内返回响应,否则会报错

这个方法还能够拿来检测代理ip的质量,如果一个代理ip在很长时间没有响应,那么添加超时之后也会报错,对应的这个ip就可以从代理ip池中删除

5. retrying模块的使用

上述方法能够加快我们整体的请求速度,但是在正常的网页浏览过成功,如果发生速度很慢的情况,我们会做的选择是刷新页面,那么在代码中,我们是否也可以刷新请求呢? 对应的,retrying模块就可以帮助我们解决

  • retrying模块的地址:https://pypi.org/project/retrying/
  • retrying 模块的使用
    • 使用retrying模块提供的retry模块 : pip install retrying
    • 通过装饰器的方式使用,让被装饰的函数反复执行
    • retry中可以传入参数stop_max_attempt_number,让函数报错后继续重新执行,达到最大执行次数的上限,如果每次都报错,整个函数报错,如果中间有一个成功,程序继续往后执行

所以我们可以结合前面的知识点和retrying模块,把我们需要反复使用的请求方法做一个简单的封装,在后续任何其他地方需要使用的时候,调用该方法就行

代码参考

# parse.py
import requests
from retrying import retry

headers = {}

@retry(stop_max_attempt_number=3) #最大重试3次,3次全部报错,才会报错
def _parse_url(url)
    response = requests.get(url, headers=headers, timeout=3) #超时的时候回报错并重试
    assert response.status_code == 200 #状态码不是200,也会报错并充实
    return response

def parse_url(url)
    try: #进行异常捕获
        response = _parse_url(url)
    except Exception as e:
        print(e)
        response = None
    return response

6. 爬虫中数据的分类

  • 结构化数据:json,xml等
    • 处理方式:直接转化为python类型
  • 非结构化数据:HTML
    • 处理方式:正则表达式、xpath

7. 数据提取之json

1. json和python数据格式区别

json python
object dict
array list
string unicode
number(int) int,long
number(real) float
true True
false False
null None

2. json数据格式的转换

json字符串 --> json.loads(json_str) --> 字典
字典 --> json.dumps(json_dict) --> json字符串

包含json的类文件对象 --> json.load() --> python数据类型
python数据类型 --> json.dump(dict, fp) --> 包含json的类文件数据

其中类文件对象的理解:

具有read()或者write()方法的对象就是类文件对象,比如f = open(“a.txt”,”r”) f就是类文件对象

具体使用方法:

#json.dumps 实现python类型转化为json字符串
#indent实现换行和空格
#ensure_ascii=False实现让中文写入的时候保持为中文
json_str = json.dumps(mydict,indent=2,ensure_ascii=False)


#json.loads 实现json字符串转化为python类型
my_dict = json.loads(json_str)


#json.dump 实现把python类型写入类文件对象
with open("temp.txt","w") as f:
    json.dump(mydict,f,ensure_ascii=False,indent=2)

# json.load 实现类文件对象中的json字符串转化为python类型
with open("temp.txt","r") as f:
    my_dict = json.load(f)

8.三元运算符

if 条件成立,if前面的结果赋值给to,否则else后面的内容赋值给to

to = "en" if lan=="zh" else "zh"

9.字典推导式

In [8]: {i:i+10 for i in range(10)}
Out[8]: {0: 10, 1: 11, 2: 12, 3: 13, 4: 14, 5: 15, 6: 16, 7: 17, 8: 18, 9: 19}

In [9]: {i:i+10 for i in range(10) if i%2==0}
Out[9]: {0: 10, 2: 12, 4: 14, 6: 16, 8: 18}

10.练习代码

1. 百度翻译判断语言类型

import requests
import json

class Fanyi:
    def __init__(self,query_string):
        self.query_string = query_string
        self.url = "https://fanyi.baidu.com/basetrans"
        self.headers = {"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"}
        self.langdetect_url = "https://fanyi.baidu.com/langdetect"

    def get_post_data(self):
        #判断需要翻译的语言类型
        # url
        data = {"query":self.query_string}
        # 发起请求 获取响应
        json_str = self.parse_url(self.langdetect_url,data)
        # 提取数据
        lan = json.loads(json_str)["lan"]
        to = "en" if lan=="zh" else "zh"
        post_data = {
            "query": self.query_string,
            "from": lan,
            "to": to,
        }
        return post_data

    def parse_url(self,url,post_data):
        response = requests.post(url=url,data=post_data,headers=self.headers)
        return response.content.decode()

    def get_ret(self,json_str):
        json_dict = json.loads(json_str)
        ret = json_dict["trans"][0]["dst"]
        print("{} 的翻译是: {}".format(self.query_string, ret))

    def run(self):
        # url
        post_data = self.get_post_data()
        # 发送请求 获取响应
        json_str = self.parse_url(self.url,post_data)
        # 提取数据
        self.get_ret(json_str)

if __name__ == '__main__':
    query_string = "hello"
    fanyi = Fanyi(query_string)
    fanyi.run()

2. 携带cookie登录人人

列表推导式的使用、字符串的切割、
cookie_dict = {i.split("=")[0]:i.split("=")[1] for i in cookie.split(";")}

import requests

# cookie使用方式一:

# url = "http://www.renren.com/969422209/profile"
# headers = {
#     "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
#     "Cookie":"anonymid=jqssugyx-z9kad7; depovince=JS; _r01_=1; JSESSIONID=abc3XQzWlaYMdhhV5S-Gw; ick_login=8f5b4e7f-950e-440a-a991-91f34253e3c6; jebe_key=967800f0-ab5e-4efe-b280-aebffd675ac8%7Ca3aa3372b122c1c97f519233b0fde327%7C1547256984705%7C1%7C1547256985274; _ga=GA1.2.1363047991.1547257026; _gid=GA1.2.305736515.1547257026; ick=7abb18fb-c8a7-4d49-912b-977556a644dd; first_login_flag=1; ln_uact=13390611285; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; wp_fold=0; wp=0; jebecookies=b248b52d-893d-41a5-b568-4f615c3b93b9|||||; _de=58E7D23B141293BCDC76A31CB46C072E; p=0e80f7d41d985d522080f7f2eb3132c29; t=a2df81d0b9027fe188b243fdf9f0bf949; societyguester=a2df81d0b9027fe188b243fdf9f0bf949; id=969422209; xnsid=c011459e; ver=7.0; loginfrom=null; jebe_key=967800f0-ab5e-4efe-b280-aebffd675ac8%7C17a6b28d4f5feaa26042443b3f1909db%7C1547260840167%7C1%7C1547260840763"
# }
# response = requests.get(url,headers=headers)
# with open('renren.html','w',encoding='utf-8')as f:
#     f.write(response.content.decode())


# cookie使用方式二
url = "http://www.renren.com/969422209/profile"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
}
cookie =  "anonymid=jqssugyx-z9kad7; depovince=JS; _r01_=1; JSESSIONID=abc3XQzWlaYMdhhV5S-Gw; ick_login=8f5b4e7f-950e-440a-a991-91f34253e3c6; jebe_key=967800f0-ab5e-4efe-b280-aebffd675ac8%7Ca3aa3372b122c1c97f519233b0fde327%7C1547256984705%7C1%7C1547256985274; _ga=GA1.2.1363047991.1547257026; _gid=GA1.2.305736515.1547257026; ick=7abb18fb-c8a7-4d49-912b-977556a644dd; first_login_flag=1; ln_uact=13390611285; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; wp_fold=0; wp=0; jebecookies=b248b52d-893d-41a5-b568-4f615c3b93b9|||||; _de=58E7D23B141293BCDC76A31CB46C072E; p=0e80f7d41d985d522080f7f2eb3132c29; t=a2df81d0b9027fe188b243fdf9f0bf949; societyguester=a2df81d0b9027fe188b243fdf9f0bf949; id=969422209; xnsid=c011459e; ver=7.0; loginfrom=null; jebe_key=967800f0-ab5e-4efe-b280-aebffd675ac8%7C17a6b28d4f5feaa26042443b3f1909db%7C1547260840167%7C1%7C1547260840763"
cookie_dict = {i.split("=")[0]:i.split("=")[1] for i in cookie.split(";")}

response = requests.get(url,headers=headers,cookies=cookie_dict)

with open('renren2.html','w',encoding='utf-8')as f:
    f.write(response.content.decode())

3. requests获取cookie

import requests

url = "http://www.baidu.com"
response = requests.get(url)
print(type(response.cookies))

cookies = requests.utils.dict_from_cookiejar(response.cookies)
print(cookies)

4. 获取json数据

import json
import requests
from pprint import pprint  #美化打印

url = "https://m.douban.com/rexxar/api/v2/subject_collection/movie_showing/items?&start=0&count=18&loc_id=108288&_=1547298724078"

headers = {"User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
           "Referer":"https://m.douban.com/movie/nowintheater?loc_id=108288"
           }

response = requests.get(url,headers=headers)
# print(response.content.decode())

# json.loads 字符串转字典
json_str = response.content.decode()
ret1 = json.loads(json_str)   
# pprint(ret1)
# print(type(ret1))

# json.dumps 字典转字符串
# with open("a.txt","w",encoding='utf-8') as f:
#     f.write(json.dumps(ret1,ensure_ascii=False,indent=4))   #写入的时候需要字典转字符串


# with open("a.txt","r",encoding='utf-8')as f:
#     # f.write(json.load(ret1))
#     ret2 = json.load(f)
#     print(type(ret2))
#     print(ret2)

with open("b.txt",'w',encoding='utf-8')as f:
    json.dump(ret1,f,ensure_ascii=False,indent=2)

5. 提取36kr网站新闻

猜你喜欢

转载自blog.csdn.net/m0_43394876/article/details/89952876