反爬虫

1.伪装useragent

Useragent是HTTP协议的中的一个字段,其作用是描述发出HTTP请求的终端的一些信息。服务器通过这个字段就可以知道要访问网站的是什么人了。每个浏览器,每个正规的爬虫都有其固定的useragent,因此只要将这个字段改为这些知名的useragent,就可以成功伪装了。不过,不推荐伪装知名爬虫,因为这些爬虫很可能有固定的IP,如百度爬虫。与此相对的,伪装浏览器的useragent是一个不错的主意,因为浏览器是任何人都可以用的,换名话说,就是没有固定IP。推荐准备若干个浏览器的useragent,然后每次发送请求的时候就从这几个useragents中随机选一个填上去。IE的几个useragent如下:

Mozilla/4.0(compatible;MSIE8.0;WindowsNT6.0)

Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.2)

Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1)

设置代码如下(假设使用JAVA+HttpClient4.1.2)

HttpGetgetMethod=newHttpGet("URL");

getMethod.setHeader("User-Agent","useragent内容");

python如下

定义一个useragent列表

list_User_Agent=[

"Mozilla/4.0(compatible;MSIE8.0;WindowsNT6.0)",

"Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.2)",

"Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1)"

]

defgetContent(url,list_User_Agent):

'''@获取403禁止访问的网页,反ip查封'''

random_header=random.choice(list_User_Agent)#在请求头列表中随机的取出一个请user_agent

printrandom_header

req=urllib2.Request(url)

req.add_header("User-Agent",random_header)

req.add_header("Host","www.tianyancha.com")

req.add_header("Referer","www.tianyancha.com")

req.add_header("CheckError","check")

req.add_header("GET",url)

req.add_header("Cookie","自己根据实际情况写")

content=urllib2.urlopen(req).read()

returncontent

getContent(url_temp,list_User_Agent)

2.login

虽然有些网站不登陆就能访问,但是它一检测到某IP的访问量有异常,就会马上提出登陆要求。如果是不带验证码的,那么果断登陆吧。不过,在登陆之前要做些准备——查清楚POST登陆请求时要附带哪些参数。我的做法是先用badboy录制登陆过程,然后将这一过程导出为jmeter文件,最后用jmeter查看登陆所需的参数。查完后,就可以登陆,具体如下所示

复制代码

DefaultHttpClienthttpclient=newDefaultHttpClient();

HttpPostpostMethod=newHttpPost("http://passport.cnblogs.com/login.aspx");//注意用post

//登陆博客园所需要的参数

Listnvps=newArrayList();

nvps.add(newBasicNameValuePair("tbUserName","风炎"));

nvps.add(newBasicNameValuePair("tbPassword","zero"));

nvps.add(newBasicNameValuePair("btnLogin","登录"));

nvps.add(newBasicNameValuePair("__EVENTTARGET",""));

nvps.add(newBasicNameValuePair("__EVENTARGUMENT",""));

nvps.add(newBasicNameValuePair("__VIEWSTATE","/wEPDwULLTE1MzYzODg2NzZkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQtjaGtSZW1lbWJlcm1QYDyKKI9af4b67Mzq2xFaL9Bt"));

nvps.add(newBasicNameValuePair("__EVENTVALIDATION","/wEWBQLWwpqPDQLyj/OQAgK3jsrkBALR55GJDgKC3IeGDE1m7t2mGlasoP1Hd9hLaFoI2G05"));

nvps.add(newBasicNameValuePair("ReturnUrl","http://www.cnblogs.com/"));

nvps.add(newBasicNameValuePair("txtReturnUrl","http://www.cnblogs.com/"));

postMethod.setEntity(newUrlEncodedFormEntity(nvps,HTTP.UTF_8));

HttpResponseresponse=httpclient.execute(postMethod);

复制代码

由于httpClient会自动管理cookie,所以接下来直接get或者post就行了。

3.使用代理

如果对方用某段时间内某IP的访问次数来判定爬虫,然后将这些爬虫的IP都封掉的话,以上伪装就失效了。对方的这个思路隐含着一个假设:爬虫的访问量必然比正常用户的大很多,因而只要使这个假设不成立就可以了。这时就该代理上场了。所谓代理就是介于用户与网站之间的第三者:用户先将请求发到代理,然后代理再发到服务器,这样看起来就像是代理在访问那个网站了。这时,服务器会将这次访问算到代理头上。同时用多个代理的话,单个IP的访问量就降下去了,于是就有可能逃过一劫。不过,这个方法最大的问题就是找到稳定的代理(有钱买代理的,可以无视这句话)。我目前是在无忧代理找,但找到的大部分都不能用,少部分能用的也不稳定。求分享好用的免费代理。

假设找到/买了N个代理,那么要如何管理这些代理呢?我的想法是做一个类似于内存池的IP池。这样做的好处是便于管理以及易于扩展。当只有一个代理时,其用法如下所示

复制代码

DefaultHttpClienthttpclient=newDefaultHttpClient();

//此代理不保证你看到的时候还存活

HttpHostproxy=newHttpHost("u120-227.static.grapesc.cz",8080);

httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);

//如果代理要认证,则加上以下语句

//httpclient.getCredentialsProvider().setCredentials(newAuthScope("proxyadress",proxyport),

//newUsernamePasswordCredentials("username","password"));

//记得将网址拆成以下形式

HttpHosttargetHost=newHttpHost("www.cnblogs.com");//网站名前面不要加http://

HttpGethttpget=newHttpGet("/FengYan/");

HttpResponseresponse=httpclient.execute(targetHost,httpget);

复制代码

补充下,如果是ADSL拨号,那么无需担心被封IP,因为一般来说,当你重新拨号时,你会得到一个不一样的IP。

4.降低访问频率

如果说找不到又免费又稳定的代理呢?那只好用最后一招了——降低访问频率。这样做可以达到与用代理一样的效果——防止被对方从访问量上看出来。当然,在抓取效率上会差很多。此外,降低访问频率只是一个指导思想,在这个思想下,可以得到很多具体做法,例如:每抓取一个页面就休息随机秒(个人感觉比固定时间的要好);限制每天抓取的页面数量。

相关推荐