1 requess模块处理cookie相关的请求
2 学习目标
3 掌握requests处理cookie的三种方法
4 1 爬虫中使用cookie
5 为了能够通过爬虫获取到登录后的页面,或者是解决通过cookie的反扒,需要使用request来处理cookie相关的请求
6
7 1.1 爬虫中使用cookie的利弊
8 带上cookie的好处
9
10 能够访问登录后的页面
11 能够实现部分反反爬
12 带上cookie的坏处
13
14 一套cookie往往对应的是一个用户的信息,请求太频繁有更大的可能性被对方识别为爬虫
15 那么上面的问题如何解决 ?使用多个账号
16 1.2 requests处理cookie的方法
17 使用requests处理cookie有三种方法:
18
19 cookie字符串放在headers中
20 把cookie字典放传给请求方法的cookies参数接收
21 使用requests提供的session模块
22 2 cookie添加在heades中
23 2.1 headers中cookie的位置
24
25
26 headers中的cookie:
27 使用分号(;)隔开
28 分号两边的类似a=b形式的表示一条cookie
29 a=b中,a表示键(name),b表示值(value)
30 在headers中仅仅使用了cookie的name和value
31 2.2 cookie的具体组成的字段
32
33
34 由于headers中对cookie仅仅使用它的name和value,所以在代码中我们仅仅需要cookie的name和value即可
35
36 2.3 在headers中使用cookie
37 复制浏览器中的cookie到代码中使用
38
39 headers = {
40 "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",
41 "Cookie":" Pycharm-26c2d973=dbb9b300-2483-478f-9f5a-16ca4580177e; Hm_lvt_98b9d8c2fd6608d564bf2ac2ae642948=1512607763; Pycharm-26c2d974=f645329f-338e-486c-82c2-29e2a0205c74; _xsrf=2|d1a3d8ea|c5b07851cbce048bd5453846445de19d|1522379036"}
42
43 requests.get(url,headers=headers)
44 注意:
45 cookie有过期时间 ,所以直接复制浏览器中的cookie可能意味着下一程序继续运行的时候需要替换代码中的cookie,对应的我们也可以通过一个程序专门来获取cookie供其他程序使用;当然也有很多网站的cookie过期时间很长,这种情况下,直接复制cookie来使用更加简单
46
47 3 使用cookies参数接收字典形式的cookie
48 cookies的形式:字典
49 cookies = {"cookie的name":"cookie的value"}
50 使用方法:
51 requests.get(url,headers=headers,cookies=cookie_dict}
52 4 使用requests.session处理cookie
53 前面使用手动的方式使用cookie,那么有没有更好的方法在requets中处理cookie呢?
54
55 requests 提供了一个叫做session类,来实现客户端和服务端的会话保持
56
57 会话保持有两个内涵:
58
59 保存cookie,下一次请求会带上前一次的cookie
60 实现和服务端的长连接,加快请求速度
61 4.1 使用方法
62 session = requests.session()
63 response = session.get(url,headers)
64 session实例在请求了一个网站后,对方服务器设置在本地的cookie会保存在session中,下一次再使用session请求对方服务器的时候,会带上前一次的cookie
65
66 4.2 动手练习:
67 动手尝试使用session来登录人人网: http://www.renren.com/PLogin.do (先不考虑这个url地址从何而来),请求体的格式:{"email":"username", "password":"password"}
68
69 思路分析
70 准备url地址和请求参数
71 构造session发送post请求
72 使用session请求个人主页,观察是否请求成功
73 5 小结
74 cookie字符串可以放在headers字典中,键为Cookie,值为cookie字符串
75 可以把cookie字符串转化为字典,使用请求方法的cookies参数接收
76 使用requests提供的session模块,能够自动实现cookie的处理,包括请求的时候携带cookie,获取响应的时候保存cookie
77
78
79
80
81
82
83 scrapy模拟登陆
84
85 应用 scrapy直接携带cookie模拟登陆的方法
86 应用 scrapy.FormRequest()发送post请求进行登陆
87 应用 scrapy.FormRequest.from_response()发送表单请求
88 1 模拟登陆的方法
89 1.1 requests模块是如何实现模拟登陆的?
90 直接携带cookies请求页面
91 找url地址,发送post请求存储cookie
92 1.2 selenium是如何模拟登陆的?
93 找到对应的input标签,输入文本点击登陆
94 1.3 scrapy有三种方法模拟登陆
95 直接携带cookies
96 找url地址,发送post请求存储cookie
97 找到对应的form表单,自动解析input标签,自动解析post请求的url地址,自动带上数据,自动发送请求
98 2 scrapy携带cookies直接获取需要登陆后的页面
99 2.1 应用场景
100 cookie过期时间很长,常见于一些不规范的网站
101 能在cookie过期之前把所有的数据拿到
102 配合其他程序使用,比如其使用selenium把登陆之后的cookie获取到保存到本地,scrapy发送请求之前先读取本地cookie
103 2.2 实现:重构scrapy的starte_rquests方法
104 scrapy中start_url是通过start_requests来进行处理的,其实现代码如下
105
106 def start_requests(self):
107 cls = self.__class__
108 if method_is_overridden(cls, Spider, 'make_requests_from_url'):
109 warnings.warn(
110 "Spider.make_requests_from_url method is deprecated; it "
111 "won't be called in future Scrapy releases. Please "
112 "override Spider.start_requests method instead (see %s.%s)." % (
113 cls.__module__, cls.__name__
114 ),
115 )
116 for url in self.start_urls:
117 yield self.make_requests_from_url(url)
118 else:
119 for url in self.start_urls:
120 yield Request(url, dont_filter=True)
121 所以对应的,如果start_url地址中的url是需要登录后才能访问的url地址,则需要重写start_request方法并在其中手动添加上cookie
122
123 2.3 携带cookies登陆github
124 测试账号 noobpythoner zhoudawei123
125
126 import scrapy
127 import re
128
129 class Login1Spider(scrapy.Spider):
130 name = 'login1'
131 allowed_domains = ['github.com']
132 start_urls = ['https://github.com/NoobPythoner'] # 这是一个需要登陆以后才能访问的页面
133
134 def start_requests(self): # 重构start_requests方法
135 # 这个cookies_str是抓包获取的
136 cookies_str = '...' # 抓包获取
137 # 将cookies_str转换为cookies_dict
138 cookies_dict = {i.split('=')[0]:i.split('=')[1] for i in cookies_str.split('; ')}
139 yield scrapy.Request(
140 self.start_urls[0],
141 callback=self.parse,
142 cookies=cookies_dict
143 )
144
145 def parse(self, response): # 通过正则表达式匹配用户名来验证是否登陆成功
146 # 正则匹配的是github的用户名
147 result_list = re.findall(r'noobpythoner|NoobPythoner', response.body.decode())
148 print(result_list)
149 pass
150 注意:
151 scrapy中cookie不能够放在headers中,在构造请求的时候有专门的cookies参数,能够接受字典形式的coookie
152 在setting中设置ROBOTS协议、USER_AGENT
153 3. scrapy.FormRequest发送post请求
154 我们知道可以通过scrapy.Request()指定method、body参数来发送post请求;那么也可以使用scrapy.FormRequest()来发送post请求
155
156 3.1 scrapy.FormRequest()的使用
157 通过scrapy.FormRequest能够发送post请求,同时需要添加fromdata参数作为请求体,以及callback
158
159 yield scrapy.FormRequest(
160 "https://github.com/session",
161 formdata={
162 "authenticity_token":authenticity_token,
163 "utf8":utf8,
164 "commit":commit,
165 "login":"noobpythoner",
166 "password":"zhoudawei123"
167 },
168 callback=self.parse_login
169 )
170 3.2 使用scrapy.FormRequest()登陆github
171 3.2.1 思路分析
172 找到post的url地址:点击登录按钮进行抓包,然后定位url地址为https://github.com/session
173
174 找到请求体的规律:分析post请求的请求体,其中包含的参数均在前一次的响应中
175
176 否登录成功:通过请求个人主页,观察是否包含用户名
177
178 3.2.2 代码实现如下:
179 import scrapy
180 import re
181
182 class Login2Spider(scrapy.Spider):
183 name = 'login2'
184 allowed_domains = ['github.com']
185 start_urls = ['https://github.com/login']
186
187 def parse(self, response):
188 authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
189 utf8 = response.xpath("//input[@name='utf8']/@value").extract_first()
190 commit = response.xpath("//input[@name='commit']/@value").extract_first()
191
192 #构造POST请求,传递给引擎
193 yield scrapy.FormRequest(
194 "https://github.com/session",
195 formdata={
196 "authenticity_token":authenticity_token,
197 "utf8":utf8,
198 "commit":commit,
199 "login":"noobpythoner",
200 "password":"***"
201 },
202 callback=self.parse_login
203 )
204
205 def parse_login(self,response):
206 ret = re.findall(r"noobpythoner|NoobPythoner",response.text)
207 print(ret)
208 4. scrapy自动提交表单
209 4.1 scrapy.Formrequest.from_response
210 它能够自动的从响应中寻找form表单,然后把formdata中的数据提交到action对应的url地址中
211
212 yield scrapy.FormRequest.from_response(
213 response, # 传入response对象,自动解析
214 # 可以通过xpath来定位form表单,当前页只有一个form表单时,将会自动定位
215 formxpath='//*[@id="login"]/form', # 可以不写
216 formdata={'login': 'noobpythoner', 'password': '***'},
217 callback=self.parse_login
218 )
219 4.2 使用scrapy.Formrequest.from_response登陆github
220 import scrapy
221 import re
222
223 class Login3Spider(scrapy.Spider):
224 name = 'login3'
225 allowed_domains = ['github.com']
226 start_urls = ['https://github.com/login']
227
228 def parse(self, response):
229 yield scrapy.FormRequest.from_response(
230 response, # 传入response对象,自动解析
231 # 可以通过xpath来定位form表单,当前页只有一个form表单时,将会自动定位
232 formxpath='//*[@id="login"]/form',
233 formdata={'login': 'noobpythoner', 'password': 'zhoudawei123'},
234 callback=self.parse_login
235 )
236
237 def parse_login(self,response):
238 ret = re.findall(r"noobpythoner|NoobPythoner", response.text)
239 print(ret)
240 5. 小技巧
241 在settings.py中通过设置COOKIES_DEBUG=TRUE 能够在终端看到cookie的传递传递过程
242
243 总结
244 start_urls中的url地址是交给start_request处理的,如有必要,可以重写start_request函数
245 直接携带cookie登陆:cookie只能传递给cookies参数接收
246 scrapy.FormRequest()发送post请求
247 scrapy.FormRequest.from_response()发送表单请求,接收的是response