二,爬虫处理cookie和session带上cookie和session的好处:
一个cookie和session往往和一个用户对应,访问太快容易被服务器检测出来爬虫1不需要cookie的时候尽量不要用
三,处理session,cookie请求1,cookie请求方式1.1直接使用浏览器抓包到的现有的cookie进行访问网站:放在header字典里面
header={"User-Agent":"Mozilla/5.0(X11;Ubuntu;Linu…)Gecko/20100101Firefox/64.0","Cookie":"csrftoken=JfnuMOvgMGZTxtCjvgfZ…6246vb2;username=chengyangkj",}r=request.get(url,headers=header)12345当然也可以在发送get请求时加上cookies的字典参数:
Cookie="csrftoken=JfnuMOvgMGZTxtCjvgfZ…6246vb2;username=chengyangkj"1但是接受的参数是字典类型的,这就需要我们适用字符串分割方法把cookie字符串转为字典形式:
cookie保存在浏览器中,很多浏览器限制一个站点最多保存20个cookiesession存在服务器中。
爬虫cookie和session1.带上cookie和session的好处能够请求到登陆后的页面2,弊端一套cookie和session往往对应一个用户,请求太快,请求次数太多,容易被识别为爬虫
不需要cookie的时候尽量不去使用cookie但是有时为了获取登陆的页面,必须发送带有cookie的请求
处理cookie和sessionsessionrequests提供了一个sessiion类,来实现客户端和服务器端的会话保持使用的方法:1.实例化一个session对象2.让session来发送get或post请求
session=requests.session()response=session.get(url,headers)例子:第一种方法:
importrequestsdefrun():headers={'User-Agent':'ozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/70.0.3538.67Safari/537.36'}data={'username':'xxxx','password':'xxxx'
if__name__=='__main__':run()
第二种方法,直接获取cookie放在headers中
第三种方式:将cookies字典化
获取登陆后的页面三种方式1.实例化session,使用session发送post请求,然后在使用session.get获取登陆后的信息2,将cookie信息加入到headers中3,将cookies字典化,然后调用
PASSWORD='[{"userId":"**","password":"**"}]'
s.headers.update({'Content-Type':'application/x-www-form-urlencoded'})payload=''forcountinrange(0,5):printcounttry:rsp=s.post('URL',data=payload)#该URL为需要获取数据页面的F12请求正文内容#print"rsp",rspbreakexceptrequests.exceptions.ConnectionError:time.sleep(1)continue#print"rsp",rspexportfile="D:/data.xls"
withopen(exportfile,'wb')asout_file:forchunkinrsp.iter_content():#将文本流保存到文件out_file.write(chunk)#若数据无效,则删除文件f=open(exportfile,'rb')lines=f.read()isinvalid=re.search("javascript",lines)if(len(lines)==0)or(isinvalidisnotNone):print"thisisemptydata,systemwilldeleteit"f.close()os.remove(exportfile)else:print"thisisvaliddata"time.sleep(40)
一、为什么要使用Cookie
它们的关系:CookieJar–派生–>FileCookieJar–派生–>MozillaCookieJar和LWPCookieJar
二、实战
1.背景介绍
在伯乐在线有这么一个有趣的模块,面向对象,它说白了就是提供了一个程序员(媛)网上相亲的平台。
它的样子是这样的:
如果登陆了账号,获取联系方式的地方是这个样子的:
在讲解之前,推荐一款抓包工具–Fiddler,可以在GoogleChrome的Google商店下载这个插件,它的样子是这样的:
可以看到,通过这个插件,我们可以很容易找到Post的FormData等信息,很方便,当然也可以用之前讲得浏览器审查元素的方式查看这些信息。
2.过程分析
在伯乐在线首页点击登陆的按钮,Fiddler的抓包内容如下:
从上图可以看出,真正请求的url是
FormData的内容记住,这些是我们编程需要用到的。user_login是用户名,user_pass是用户密码。
从上图可以看出,此刻真正请求的url是
3.测试
1)将Cookie保存到变量中
首先,我们先利用CookieJar对象实现获取cookie的功能,存储到变量中,先来感受一下:
2)保存Cookie到文件
在上面的方法中,我们将cookie保存到了cookie这个变量中,如果我们想将cookie保存到文件中该怎么做呢?方便以后直接读取文件使用,这时,我们就要用到FileCookieJar这个对象了,在这里我们使用它的子类MozillaCookieJar来实现Cookie的保存,编写代码如下:
if__name__=='__main__':
ignore_discard的意思是即使cookies将被丢弃也将它保存下来;
ignore_expires的意思是如果在该文件中cookies已经存在,则覆盖原文件写入。
在这里,我们将这两个全部设置为True。
运行之后,cookies将被保存到cookie.txt文件中。我们可以查看自己查看下cookie.txt这个文件的内容。
3)从文件中获取Cookie并访问
我们已经做到把Cookie保存到文件中了,如果以后想使用,可以利用下面的方法来读取cookie并访问网站,感受一下:
4.编写代码
我们利用CookieJar对象实现获取cookie的功能,存储到变量中。然后使用这个cookie变量创建opener,使用这个设置好cookie的opener即可模拟登陆,同笔记四中讲到的IP代理的使用方法类似。
创建cookie_test.py文件,编写代码如下:
1.获取需要提交的数据
使用chrome的Network或者fiddler可以很轻易的得到我们想要的数据,这里使用fiddler举例。
打开fiddler
输入完账户信息和验证码后,为了方便查找,推荐点击清除清空会话记录
点击右下角的花朵即可送一朵花,左上角显示当前剩余数量,规则是每两分钟花朵数量恢复成100,每个账号可以一直送。如果仅仅是点击花朵形状可以一直送花的话,是很简单的,关键问题在于它时不时会跳出滑动验证码,如下图所示,这时候就需要解决验证码的问题了,当然了,这部分代码我是参考的别人的。
defopen(self):self.driver.get(self.url)
defget_pic(self):time.sleep(2)target=browser.find_element_by_class_name("yidun_bg-img")template=browser.find_element_by_class_name("yidun_jigsaw")target_link=target.get_attribute('src')template_link=template.get_attribute('src')target_img=Image.open(BytesIO(requests.get(target_link).content))template_img=Image.open(BytesIO(requests.get(template_link).content))target_img.save('target.jpg')template_img.save('template.png')size_orign=target.sizelocal_img=Image.open('target.jpg')size_loc=local_img.sizeself.zoom=320/int(size_loc[0])
defget_tracks(self,distance):print(distance)distance+=20v=0t=0.2forward_tracks=[]current=0mid=distance*3/5whilecurrent back_tracks=[-3,-3,-2,-2,-2,-2,-2,-1,-1,-1]return{'forward_tracks':forward_tracks,'back_tracks':back_tracks} defmatch(self,target,template):img_rgb=cv2.imread(target)img_gray=cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)template=cv2.imread(template,0)run=1w,h=template.shape[::-1]print(w,h)res=cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)#使用二分法查找阈值的精确值L=0R=1whilerun<20:run+=1threshold=(R+L)/2ifthreshold<0:print('Error')returnNoneloc=np.where(res>=threshold)#print(len(loc[1]))iflen(loc[1])>1:L+=(R-L)/2eliflen(loc[1])==1:print('目标区域起点x坐标为:%d'%loc[1][0])breakeliflen(loc[1])<1:R-=(R-L)/2 returnloc[1][0] defcrack_slider(self,browser):#self.open()target='target.jpg'template='template.png'self.get_pic()distance=self.match(target,template)zoo=1.36#缩放系数,需要自己调整大小tracks=self.get_tracks((distance+7)*zoo)#对位移的缩放计算#print(tracks)slider=browser.find_element_by_class_name("yidun_slider")ActionChains(browser).click_and_hold(slider).perform() fortrackintracks['forward_tracks']:ActionChains(browser).move_by_offset(xoffset=track,yoffset=0).perform() time.sleep(0.5)forback_tracksintracks['back_tracks']:ActionChains(browser).move_by_offset(xoffset=back_tracks,yoffset=0).perform() ActionChains(browser).move_by_offset(xoffset=-3,yoffset=0).perform()ActionChains(browser).move_by_offset(xoffset=3,yoffset=0).perform()time.sleep(0.5)ActionChains(browser).release().perform()try:failure=WebDriverWait(browser,5).until(EC.text_to_be_present_in_element((By.CLASS_NAME,'yidun_tips__text'),'向右滑动滑块填充拼图'))print(failure)except:print('验证成功')returnNone iffailure:self.crack_slider(browser) #if__name__=='__main__':browser=webdriver.Chrome() browser.implicitly_wait(10)browser.switch_to_window(browser.window_handles[-1])c=CrackSlider()k=1foriinrange(1,70000):try:elem=browser.find_element_by_class_name("idol_vote_info")elem.click()time.sleep(0.2)#设置点击50次刷新一次ifk%50==0:browser.refresh()#刷新方法refreshprint('testpass:refreshsuccessful')#点击110次休眠50s,可以自己设置ifk%110==0:print("click",k)time.sleep(50)k+=1except:print('-----需要验证-----')c.crack_slider(browser)不过代码仍然有不完善的地方,因为验证码拖动是借鉴的别人的代码,我也没有深入理解,这个验证大概需要拖动两三次才验证成功,不过我觉得已经够用了。还有程序偶尔会报错停止运行,这时候就可以再写一个小程序,监控这个程序有没有挂掉,挂掉的话重新运行该程序即可。监控的程序runner.py如下: importosfromsysimportargv if__name__=='__main__':whileos.system('python'+''.join(argv[1:])):print('Haltedbyexception,restart')在命令行中输入