模拟登录
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