当前位置: 首页 > 科技观察

常见反爬虫机制的应对策略

时间:2023-03-14 23:33:14 科技观察

爬虫与反爬虫,这对相爱相杀的情侣简直可以写出一段波澜壮阔的奋斗史。大数据时代,数据就是金钱。许多公司在网站上使用了反爬虫机制,以防止网页上的数据被爬虫爬取。但是,如果反爬虫机制过于严格,可能会误伤真实的用户请求;如果一定要对抗爬虫,保证极低的意外伤害率,那么研发成本就会增加。简单低级的爬虫速度快,伪装性低。如果没有反爬虫机制,他们可以快速抓取大量数据,甚至会因为请求过多而导致服务器无法正常工作。伪装度高的爬虫爬取速度慢,对服务器的负担也比较小。所以网站反爬虫的重点也是那种简单粗暴的爬虫,反爬机制也会让高度伪装的爬虫获取数据。毕竟伪装程度高的爬虫和真实用户并没有太大区别。本文主要讨论在使用Scrapy框架时如何应对常见的反爬机制。headerinspection最简单的反爬机制就是检查HTTP请求的header信息,包括User-Agent、Referer、Cookies等,User-AgentUser-Agent就是检查用户使用的客户端类型和版本。在Scrapy中,一般是在下载器中间件中进行处理。比如在setting.py中创建一个包含很多浏览器User-Agent的列表,然后新建一个random_user_agent文件:'USER_AGENT_LIST'])ifua:request.headers.setdefault('User-Agent',ua)这样可以在每次请求中随机选择一个真实的浏览器User-Agent。RefererReferer是查看请求来自哪里,通常可以用来判断图片的盗链。在Scrapy中,如果一个页面url是从之前爬取的页面中提取出来的,Scrapy会自动使用之前爬取的页面url作为Referfer。你也可以按照上面的方式自己定义Referfer字段。Cookies网站可能会检测cookie中session_id的使用次数,如果超过限制,就会触发反爬策略。所以你可以在Scrapy中设置COOKIES_ENABLED=False来发出不带Cookies的请求。也有强制开启Cookies的网站,这时候就会有点麻烦。也可以写一个简单的爬虫,定期向目标网站发送不带cookie的请求,提取响应中的Set-cookie字段信息并保存。抓取网页时,将存储的Cookies带入Headers中。X-Forwarded-For在请求头中添加X-Forwarded-For字段来声明自己是透明代理服务器。有些网站在代理服务器上会比较软。X-Forwarded-Forheader的一般格式如下:X-Forwarded-For:client1,proxy1,proxy2这里将client1和proxy1设置为随机IP地址,将自己的请求伪装成随机IP生成的请求的代理。但是由于X-Forwarded-For是可以随意篡改的,很多网站不会相信这个值。限制IP请求数如果某个IP的请求速度过快,就会触发反爬虫机制。当然可以通过放慢爬取速度来绕过,代价是大大增加爬取时间。另一种方法是添加代理。很简单,在下载器中间件中添加:request.meta['proxy']='http://'+'proxy_host'+':'+proxy_port然后为每个请求使用不同的代理IP。但是,问题是如何获取大量的代理IP?可以自己写一个IP代理获取和维护系统,定期从各种公开免费代理IP的网站上爬取免费IP代理,然后定期扫描这些IP和端口是否可用,不可用时及时清理代理IP.这样就有了一个动态代理库,每次请求都会从库中随机选择一个代理。但是,这种方案的缺点也很明显。系统本身的获取和维护费时费力,而且这种免费代理的数量也不多,稳定性也比较差。如果一定要用代理,也可以购买一些稳定的代理服务。这些服务中的大多数都使用经过身份验证的代理。在requests库中添加带认证的代理很简单,proxies={"http":"http://user:pass@10.10.1.10:3128/",}但是Scrapy不支持这种认证方式,需要传递认证信息经过base64编码后,在Headers中添加Proxy-Authorization字段:importbase64#Setthelocationoftheproxyproxy_string=choice(self._get_proxies_from_file('proxies.txt'))#user:pass@ip:portproxy_items=proxy_string.split('@')request.meta['proxy']="http://%s"%proxy_items[1]#setupbasicauthenticationfortheproxyuser_pass=base64.encodestring(proxy_items[0])request.headers['Proxy-Authorization']='Basic'+user_pass动态加载现在越来越多的网站使用ajax来动态加载内容。这时候可以先拦截ajax请求,分析一下。可以根据ajax请求构造相应的API请求URL,直接获取想要的内容,一般为json格式。无需解析HTML。但是很多时候ajax请求会被后端鉴权,无法直接构造url获取。这时候可以通过PhantomJS+Selenium模拟浏览器的行为,抓取js渲染的页面。需要注意的是,使用Selenium后,请求将不再被Scrapy的Downloader执行,所以之前添加的请求头信息将失效。您需要将headers={...}forkey,valueinheaders.iteritems():webdriver添加到Selenium.DesiredCapabilities.PHANTOMJS['phantomjs.page.customHeaders.{}'.format(key)]=value另外,调用PhantomJs需要指定PhantomJs的可执行文件路径,一般会添加到系统的path路径中,这样程序在执行的时候,会自动去该路径中寻找。我们的爬虫很多时候都是放在crontab里面定时执行的,而crontab里面的环境变量和系统的环境变量是不一样的,所以无法加载PhamtonJs需要的路径,所以最好的方式是在声明的时候指定路径:driver=网络驱动程序。PhantomJS(executable_path='/usr/local/bin/phantomjs')