最近在爬拉勾,遇到一些问题,给后来的小伙伴总结一些经验。这里我们只谈技术,不谈代码。如果不是为了学习经验的话,还请移步百度。
首先说一下拉勾的反爬:IP频率限制,头信息限制,cookie时时验证。
IP频率限制:这是最常用,也是最有效的反爬机制之一,并没有测试拉勾的爬取阈值是多少。有兴趣的可以自己去测一下。头信息限制:拉勾对头信息的要求很高,如果你的头信息不全,会得到302或者无法访问的情况,如果你的头信息多了,有可能会给你投毒。这也很好解决,针对每个类型的URL定制headerscookie时时验证:这是拉勾做的最好的反爬机制了,这里的时时可不是指每小时验证一次cookie,而是每个请求验证一次cookie。有人说这很正常啊,难道其他网站不是每条请求都验证吗?拉勾做的不同的地方在于,登录之后的cookie在访问一个新的URL之后是变化的,也就是说你从网页复制的cookie在爬虫中只能使用一次就会失效。而游客cookie则是每请求5个URL就会强制302。cookie本质上是一些键值对的集合,可以粗略的看成字典,而拉勾每次请求的cookie变化的主要有三个参数,
LGRID:值为20190426111643-b773c320-67d1-11e9-b7c1-525400f775ce,前面的很容易看出是时间,后面的依我看应该是随机生成的UUID(不知道的请百度)Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6:值是一个时间戳,和上一个参数的时间差只有几秒,或者完全相同,这个键前面是固定的,后面应该是某个的哈希值。_gat:要么不存在,要么值为1经过很多值对比和百度,发现变化的时间为上一次访问的时间,_gat暂时还不知道有什么作用,先不理他。那么找到cookie值的不同有什么用呢?难道还能找到他们的规律不成。当然不是,这些有的是随机生成的值,肯定没有规律的。上面的这些话只是在说明拉勾的cookie是一直变化的,所以直接复制cookie使用是不可行的。
这里先记录一下我遇到的两个小问题,后面再说怎么解决拉勾cookie:
1、 requests的session是不能维持你直接从浏览器复制然后加入到headers的cookie的,也就是说,你第一次访问的时候是携带cookie的,但你在使用session的时候,session还是没有cookie。解决方法:将字符串的cookie转化为字典,再转化为cookiejar对象传给session。 具体代码见: https://blog.csdn.net/a583179/article/details/78904645 https://blog.csdn.net/falseen/article/details/46962011
2、在使用requests的时候出现:UnicodeEncodeError: ‘latin-1’ codec can’t encode character ‘\uff08’ in position 21: ordinal not in range(256) 原因:请求头中含有特殊字符,无法被编码为’latin-1’。我的程序出错是因为referer参数的URL是我自己构建的,包含中文或一些其他字符。 解决方法:使用urllib.request.quote(URL)转码一下就行。另外,我百度的时候,出现这种错误的大多是连接数据库时的错误。所以还是要看你的情况。
既然每次访问之后的cookie是变化的,那么浏览器是怎么得到这种变化的呢?浏览器能得到内容说明他时时更新了cookie。最先想到的肯定是每次请求的响应头里可能携带Set-Cookie参数对cookie做了修改。但是并没有,就算有的请求的响应头里确实有Set-Cookie,但也不是修改我上面说的两个关于上一次访问时间的值。
更新时间:2019-05-20
关于cookie的变化,是因为拉勾在访问某个页面之后,会携带这一次的一些请求信息请求另一个API,API会返回set-cookie来修改cookie,请求链接大概为 a.lagou.com/collect? 。而且它还会请求Google的一个接口,参数几乎和这个API的一样,猜测作用是验证和记录。但我模拟这两个请求发现,携带登录的cookie也只能访问两个页面就302了。可能是我携带的参数不正确,因为请求API所需的参数是20个,要想一个一个找到他们的构造方式太麻烦,所以我是直接复制的,通过几次的变化来猜测参数,所以可能不准确。而且拉勾的程序员很精明,参数的命名全部不超过三个字符,通过抓包来全局搜索根本就找不到,比如参数a、参数z等。
另外在测试的过程中遇到一个小问题: requests的session更新cookie再去发起请求之后,你已经更新的cookie里的参数和值是不会变化的,在服务器返回Set-cookie之后,session做的并不是更新某一些参数而是添加它们,这就导致了cookie中有两个同样的参数,和拉勾原本的cookie不一致。 举个例子: 我们原本的cookie字典为{‘a’:1111,‘b’:2222},然后把它加入到session中 服务器返回的set-cookie为’a’ = 0000,那么你现在的cookie就变成了{‘a’:1111,‘a’:0000,‘b’:2222}。而不是直接更新a。(这只是用字典举例,cookie对象并不是完全的对象,因为可以包含相同的键)。但是你再次请求的时候,它才会将后面添加的那个参数更新。暂时没有找到解决方法,只能自己更新cookie,而不使用session。
我在拉勾的cookie上浪费了大量的时间,取得的效果比较低,其实在实际爬去过程中根本不需要携带登录的cookie。只需要使用游客cookie就能拿到所需的数据,当然当你某个IP获取了大量的游客cookie之后会被封,但是爬虫想要大数据量,代理是肯定要的。
百度上的一些文章都是每发送一个POST请求前都向目标网页发送一个GET请求来更新cookie,我测试了一下,这并不是更新cookie而是重新获取一个新的cookie,这样是不可取的,一个游客cookie实际可以发送10个POST请求,5个GET请求,这样做就太浪费cookie,可能直接导致IP被封的时间提前很多。所以我们可以每发送10个POST请求就重新获取一个cookie(中间可以加一个适当的延迟),再加上代理池完全可以拿到拉勾整站的职位数据。我并没有测试一个IP爬多长时间会被封,我试着间隔一秒来运行了10分钟也没有问题,这就已经足够满足实际需求了。
原文博客:https://blog.csdn.net/Qwertyuiop2016/ 现在这个是小号,给爬虫用的
欢迎关注我的微信公众号,分享我的学习经验和一些觉得不错的资源。如果有问题的话,也可以在微信公众号联系我。