概述
由于要准备测试数据,不得不大量爬取某个网站的内容。为了防止被封,特意将爬虫设计为单线程同步的爬虫。结果在爬了大约3万个页面的时候,对方发回Access Denied。等一段时间后再启动爬虫,结果还是Access Denied。这时才明白这样的想法太天真了,当初就应该找其它方法来避免才对。而本文则记述了这些其它方法。
1. 伪装user agent
User agent 是HTTP协议的中的一个字段, 其作用是描述发出HTTP请求的终端的一些信息。 服务器通过这个字段就可以知道要访问网站的是什么人了。每个浏览器,每个正规的爬虫都有其固定的user agent,因此只要将这个字段改为这些知名的user agent,就可以成功伪装了。不过,不推荐伪装知名爬虫,因为这些爬虫很可能有固定的IP,如百度爬虫。与此相对的,伪装浏览器的user agent是一个不错的主意,因为浏览器是任何人都可以用的,换名话说,就是没有固定IP。推荐准备若干个浏览器的user agent,然后每次发送请求的时候就从这几个user agents中随机选一个填上去。
IE的几个user agent如下:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
设置代码如下(假设使用JAVA + HttpClient 4.1.2):
HttpGet getMethod = new HttpGet("URL");
getMethod.setHeader("User-Agent", "user agent内容");
2.登陆网站
虽然有些网站不登陆就能访问,但是它一检测到某IP的访问量有异常,就会马上提出登陆要求。如果是不带验证码的,那么果断登陆吧。不过,在登陆之前要做些准备——查清楚POST登陆请求时要附带哪些参数。我的做法是先用badboy录制登陆过程,然后将这一过程导出为jmeter文件,最后用jmeter查看登陆所需的参数。查完后,就可以登陆,具体如下所示:
DefaultHttpClient httpclient = newDefaultHttpClient();
HttpPost postMethod= new HttpPost("http://passport.cnblogs.com/login.aspx"); //注意用post//登陆博客园所需要的参数
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("tbUserName", "风炎"));
nvps.add(new BasicNameValuePair("tbPassword", "zero"));
nvps.add(new BasicNameValuePair("btnLogin", "登 录"));
nvps.add(new BasicNameValuePair("__EVENTTARGET", ""));
nvps.add(new BasicNameValuePair("__EVENTARGUMENT", ""));
nvps.add(new BasicNameValuePair("__VIEWSTATE", "/wEPDwULLTE1MzYzODg2NzZkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQtjaGtSZW1lbWJlcm1QYDyKKI9af4b67Mzq2xFaL9Bt"));
nvps.add(new BasicNameValuePair("__EVENTVALIDATION", "/wEWBQLWwpqPDQLyj/OQAgK3jsrkBALR55GJDgKC3IeGDE1m7t2mGlasoP1Hd9hLaFoI2G05"));
nvps.add(new BasicNameValuePair("ReturnUrl", "http://www.cnblogs.com/"));
nvps.add(new BasicNameValuePair("txtReturnUrl", "http://www.cnblogs.com/"));
postMethod.setEntity(newUrlEncodedFormEntity(nvps, HTTP.UTF_8));
HttpResponse response= httpclient.execute(postMethod);
由于httpClient会自动管理cookie,所以接下来直接get或者post就行了。
3. 使用代理
如果对方用某段时间内某IP的访问次数来判定爬虫,然后将这些爬虫的IP都封掉的话,以上伪装就失效了。对方的这个思路隐含着一个假设:爬虫的访问量必然比正常用户的大很多,因而只要使这个假设不成立就可以了。这时就该代理上场了。所谓代理就是介于用户与网站之间的第三者:用户先将请求发到代理,然后代理再发到服务器,这样看起来就像是代理在访问那个网站了。这时,服务器会将这次访问算到代理头上。同时用多个代理的话,单个IP的访问量就降下去了,于是就有可能逃过一劫。不过,这个方法最大的问题就是找到稳定的代理(有钱买代理的,可以无视这句话)。我目前是在无忧代理找,但找到的大部分都不能用,少部分能用的也不稳定。求分享好用的免费代理。
假设找到/买了N个代理,那么要如何管理这些代理呢?我的想法是做一个类似于内存池的IP池。这样做的好处是便于管理以及易于扩展。当只有一个代理时,其用法如下所示:
DefaultHttpClient httpclient = newDefaultHttpClient();//此代理不保证你看到的时候还存活
HttpHost proxy = new HttpHost("u120-227.static.grapesc.cz", 8080);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);//如果代理要认证,则加上以下语句//httpclient.getCredentialsProvider().setCredentials(new AuthScope("proxy adress", proxy port),//new UsernamePasswordCredentials("username", "password"));//记得将网址拆成以下形式
HttpHost targetHost = new HttpHost("www.cnblogs.com"); //网站名前面不要加http://
HttpGet httpget = new HttpGet("/FengYan/");
HttpResponse response= httpclient.execute(targetHost, httpget);
补充下,如果是
ADSL拨号,那么无需担心被封IP,因为一般来说,当你重新拨号时,你会得到一个不一样的IP。
4. 降低访问频率
5. 总结
原文网址:http://www.verydemo.com/cj.jsp?c=33&u=dang-pa-chong-bei-ju-jue-shi-accessdenied
最后
以上就是震动店员为你收集整理的当爬虫被拒绝时(Access Denied)的全部内容,希望文章能够帮你解决当爬虫被拒绝时(Access Denied)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复