模拟登录

  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
原文地址:https://www.cnblogs.com/wanglinjie/p/9337706.html