`
pxlfxl2
  • 浏览: 51074 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

伪装豆瓣爬虫程序——如何解决豆瓣禁用爬虫程序?

 
阅读更多

最近因为业务需要,要将豆瓣上的图书以及影视信息抓取下来,网页抓取其实很简单,很快就完成,但是系统还没上线就发现了问题,豆瓣会根据请求分析客户的行为,判断是否是机器人,如果判断为机器人,将要求输入验证码,最终导致抓取不到数据。

要解决这个问题,主要就两个思路,一个是识别验证码,当要求输入验证码时,识别图片中的验证码;另外一方案是伪装成正常访问,绕过豆瓣的分析程序。前一种方案受限于验证码识别率太低,很难满足需求,最终只能考虑第二种方案了。

通过分析豆瓣的分析判断机器人的实际情况,发现豆瓣是根据ip以及cookie信息统计访问频率来确定是否为“机器人”,有以下几种实际情况,1.不带cookie信息访问,快速访问一段时间,ip会被禁掉;2.带cookie访问,快速访问一段时间,请求会被禁掉,这时候清掉cookie,可以恢复正常访问。基于这个测试结果,可以采用一个简单的方案:

       1.第一次请求没有cookie信息,但记录下返回的cookie.

       2.后面每个请求都带上这个cookie信息.

       3.如果请求被跳转到验证码页面,就不带cookie重试,并记录返回的cookie信息

       4.下一次请求带上新的cookie信息。

重复2到4步骤。

 

       代码:

       1.简单的cookie manager:

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 简单的Cookie Manager,按照顶级域名管理Cookie信息
 * @author <a href="mailto:jingyu@taohua.com">惊羽</a>
 *
 */
class CookieManager implements Serializable{
	private static final long serialVersionUID = 292218695837624307L;
	private static CookieManager cookieManager = new CookieManager();
	private Map<String,Map<String,String>> cookies = new ConcurrentHashMap<String, Map<String,String>>();
	
	private CookieManager(){}
	/**
	 * 根据域名获取对应的Cookie
	 * @param domain
	 * @return
	 */
	public String getCookies(String domain){
		Map<String, String> domainCookies = cookies.get(getTopLevelDomain(domain));
		if(domainCookies != null){
			StringBuilder sb = new StringBuilder();
			boolean isFirst = true;
			for(Map.Entry<String, String> cookieEntry : domainCookies.entrySet()){
				if(!isFirst){
					sb.append("; ");
				}else{
					isFirst = false;
				}
				sb.append(cookieEntry.getKey())
			      .append("=")
			      .append(cookieEntry.getValue());
			}
			return sb.toString();
		}
		return "";
	}
	
	/**
	 *
	 * 设置Cookie值
	 * @param domain
	 * @param cookiesString
	 */
	public void setCookies(String domain,String cookiesString){
		Map<String, String> domainCookies = cookies.get(getTopLevelDomain(domain));
		if(domainCookies == null){
			domainCookies = new ConcurrentHashMap<String, String>();
			cookies.put(getTopLevelDomain(domain), domainCookies);
		}
		String[] cookies = cookiesString.split("; ");
		for (String cookie : cookies) {
			if(cookie != null && !cookie.trim().isEmpty()
					&& cookie.indexOf("=") > 0){
				int equalMarkIndex = cookie.indexOf("=");
				String key = cookie.substring(0,equalMarkIndex);
				String value = cookie.substring(equalMarkIndex+1);
				domainCookies.put(key, value);
			}
		}
	}
	/**
	 * 删除域名下所有的Cookie
	 * @param domain
	 */
	public void removeCookies(String domain){
		cookies.remove(getTopLevelDomain(domain));
	}
	
	/**
	 * 获取CookieManager的实例
	 * @return
	 */
	public static CookieManager getInstance(){
		return cookieManager;
	}
	
	/**
	 * 获取域名的顶级域名
	 * @param domain
	 * @return
	 */
	public String getTopLevelDomain(String domain){
		if(domain == null){
			return null;
		}
		if(!domainToTopLevelDomainMap.containsKey(domain)){
			String[] splits = domain.split("\\.");
			domainToTopLevelDomainMap.put(domain, (splits[splits.length-2] + "." + splits[splits.length -1]));
		}
		return domainToTopLevelDomainMap.get(domain);
	}
	/**
	 * 存储域名与其顶级域名之间映射关系,避免重复的计算顶级域名
	 */
	private Map<String,String> domainToTopLevelDomainMap = new ConcurrentHashMap<String, String>();
}
 

       2. 包装HttpURLConnection,实现请求失败自动清除cookie并重试的功能。

 

public class HttpURLConnectionWrapper extends HttpURLConnection {
	
	HttpURLConnection httpURLConnection;
	//简单的CookieManager
	CookieManager cookieManager = CookieManager.getInstance();
	
	public HttpURLConnectionWrapper(URL u) throws IOException {
		super(u);
		httpURLConnection = (HttpURLConnection) u.openConnection();
		setFollowRedirects(false);
		fillRequestHeadField();
	}
	/**
	 * 填充Request Header信息
	 */
	private void fillRequestHeadField(){
		httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0");
		httpURLConnection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		httpURLConnection.setRequestProperty("Accept-Language", "zh-cn,zh;q=0.5");
		httpURLConnection.setRequestProperty("Accept-Encoding", "GB2312,utf-8;q=0.7,*;q=0.7");
		httpURLConnection.setRequestProperty("Referer", "http://movie.douban.com/");
		httpURLConnection.setRequestProperty("Cache-Control", "max-age=0");
		httpURLConnection.setRequestProperty("Cookie", cookieManager.getCookies(url.getHost()));
		
	}

	@Override
	public InputStream getInputStream() throws IOException {
		InputStream is = httpURLConnection.getInputStream();
		//取到输入流中后处理Cookie信息
		resolveCookies();
		int responseCode = getResponseCode();
		if(responseCode != 200 && responseCode != 404 ){
			//清除cookie并重新发请求
			CookieManager.getInstance().removeCookies(url.getHost());
			try{
				httpURLConnection.disconnect();
				is.close();
			}catch (Exception e) {
			}
			httpURLConnection = (HttpURLConnection) this.getURL().openConnection();
			setFollowRedirects(false);
			fillRequestHeadField();
			is = httpURLConnection.getInputStream();
		}
		return is;
	}
	private void resolveCookies(){
		List<String> setCookies = getHeaderFields().get("Set-Cookie");
		if(setCookies != null && !setCookies.isEmpty()){
			for (String setCookie : setCookies) {
				cookieManager.setCookies(this.url.getHost(), setCookie);
			}	
		}
	}
.........
}
 

 

分享到:
评论
7 楼 pxlfxl2 2013-01-30  
KeySeeker 写道
博主问一下,刚刚我尝试了一下,我用的是httpclient包,然后不断地进行访问,当出现403的时候就将里面的cookie给删除掉,结果这个时候还是登陆不了,依然403,不知是不是我没有理解你的文章的意思啊,求指导阿!

这都差不多一年前的方法了,现在不知道好不好用呢,你别用httpclient试试,主要代码我已经贴出来了。
6 楼 KeySeeker 2013-01-23  
博主问一下,刚刚我尝试了一下,我用的是httpclient包,然后不断地进行访问,当出现403的时候就将里面的cookie给删除掉,结果这个时候还是登陆不了,依然403,不知是不是我没有理解你的文章的意思啊,求指导阿!
5 楼 KeySeeker 2013-01-23  
carlosfu 写道
如果是第一种情况,怎么处理?
1.不带cookie信息访问,快速访问一段时间,ip会被禁掉

那样应该是使用代理服务器来登陆把,这是比较好的解决方案le.刚刚我尝试了一下博主的方案,即使带cookie访问,如果403的话,删除cookie再重新访问,也依然会被禁用.
4 楼 carlosfu 2013-01-17  
如果是第一种情况,怎么处理?
1.不带cookie信息访问,快速访问一段时间,ip会被禁掉
3 楼 pxlfxl2 2012-04-28  
e_soft 写道
抓别人数据 还大张旗鼓写出来啊 呵呵


我知道看到网上有很多人遇到这个问题,没有人给解决方案,那我就随便写写,分享一下啦……

我把问题写出了,豆瓣也可以想办法屏蔽掉这个漏洞的
2 楼 hanmiao 2012-04-27  
你太高调了,这种事情自己做了就算了,别明着写出来...
1 楼 e_soft 2012-04-27  
抓别人数据 还大张旗鼓写出来啊 呵呵

相关推荐

    豆瓣爬虫程序.rar

    《豆瓣爬虫程序详解及其应用》 爬虫技术在当今信息时代扮演着至关重要的角色,它可以帮助我们自动化地从互联网上收集、整理和分析数据。豆瓣作为国内知名的影评、图书和音乐分享平台,其丰富的用户评价和评分数据对...

    微信小程序——豆瓣图书(截图+源码).zip

    微信小程序——豆瓣图书(截图+源码).zip 微信小程序——豆瓣图书(截图+源码).zip 微信小程序——豆瓣图书(截图+源码).zip 微信小程序——豆瓣图书(截图+源码).zip 微信小程序——豆瓣图书(截图+源码).zip ...

    微信小程序——豆瓣电影(截图+源码).zip

    微信小程序——豆瓣电影(截图+源码).zip 微信小程序——豆瓣电影(截图+源码).zip 微信小程序——豆瓣电影(截图+源码).zip 微信小程序——豆瓣电影(截图+源码).zip 微信小程序——豆瓣电影(截图+源码).zip ...

    豆瓣网爬虫程序

    【标题】:豆瓣网爬虫程序 在编程领域,网络爬虫是一种自动化获取网页信息的工具,常用于数据挖掘和数据分析。"豆瓣网爬虫程序"是一个使用Python语言编写的项目,旨在帮助初学者理解爬虫的基本原理和实现方法。豆瓣...

    Python爬虫程序源代码爬取豆瓣TOP250排行榜数据电影名称评分导演演员等信息

    Python爬虫程序源代码爬取豆瓣TOP250排行榜数据电影名称评分导演演员等信息 知识领域: 数据爬取、数据分析、Python编程技术关键词: Python、网络爬虫、数据抓取、数据处理内容关键词: 豆瓣电影、排行榜、数据...

    22级2班 豆瓣爬虫程序(完整版).ipynb

    22级2班 豆瓣爬虫程序(完整版).ipynb

    豆瓣电影python爬虫程序

    这是一个简单的Python爬虫程序,旨在从豆瓣电影网站中提取电影信息。通过使用网络爬虫技术,该程序可以自动从豆瓣电影网页中抓取电影的名称、评分、演员、导演等信息,然后将这些数据存储或进一步处理,例如制作数据...

    python豆瓣电影爬虫

    **Python 豆瓣电影爬虫** Python 是一种流行的编程语言,因其简洁的语法和强大的功能在数据分析、网络爬虫领域被广泛使用。本项目旨在利用Python构建一个爬虫,爬取豆瓣电影Top250的电影信息,包括电影名称、评分、...

    豆瓣电影top250爬虫

    "豆瓣电影top250爬虫"项目是一个专门针对豆瓣网站上电影Top250排行榜的数据抓取程序。这个爬虫的独特之处在于,它没有依赖像BeautifulSoup这样的成熟的HTML解析库,而是采用了纯字符串搜索的方式来解析网页内容,这...

    豆瓣爬虫租房.zip

    爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的...

    微信小程序仿豆瓣电影源码

    微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小...

    豆瓣电影python爬虫程序.zip

    【标题】:“豆瓣电影python爬虫程序.zip”指的是一个使用Python编程语言编写的爬虫程序,专门用于抓取豆瓣电影网站上的数据。这个压缩包包含了实现这一功能的源代码和其他相关资源。 【描述】:“python爬虫程序”...

    python豆瓣图书爬虫

    Python豆瓣图书爬虫是一种利用Python编程语言来抓取和处理豆瓣网站上图书信息的程序。这个项目主要涉及以下几个核心知识点: 1. **Python基础**:Python是实现爬虫的常用语言,因为它语法简洁,易于学习,并且有...

    豆瓣悦读——让阅读更有乐趣

    《豆瓣悦读——让阅读更有乐趣》 豆瓣悦读是一款专为阅读豆瓣平台上的文章而设计的应用,旨在提供一种更为便捷、舒适的阅读体验,让用户能够沉浸在文字的世界里,免受网页翻页的困扰。这款应用将豆瓣上的优质内容...

    豆瓣250_python豆瓣爬虫_

    标题中的“豆瓣250_python豆瓣爬虫”指的是使用Python编程语言编写的一个网络爬虫程序,目标是抓取豆瓣电影网站上评分最高的前250部电影的相关信息。这个爬虫程序可以帮助用户自动化地获取这些电影的数据,而无需...

    01-豆瓣爬虫_爬虫_

    标题中的“01-豆瓣爬虫”表明我们将讨论一个关于抓取豆瓣网站数据的网络爬虫项目。这个项目可能是系列教程或代码实现的第一部分,主要关注如何构建爬虫来获取豆瓣平台上的信息。 描述中提到“爬取豆瓣网页,并采用...

    微信小程序 豆瓣电影 (源码)

    微信小程序 豆瓣电影 (源码)微信小程序 豆瓣电影 (源码)微信小程序 豆瓣电影 (源码)微信小程序 豆瓣电影 (源码)微信小程序 豆瓣电影 (源码)微信小程序 豆瓣电影 (源码)微信小程序 豆瓣电影 (源码)微信小程序 豆瓣...

    基于python爬虫对豆瓣影评分析进行爬取的课程设计.zip

    在本课程设计中,我们将深入探讨如何利用Python爬虫技术来获取并分析豆瓣电影网站上的影评数据。Python爬虫是获取大量网络数据的有效手段,尤其适用于数据分析和挖掘项目。以下是一些关键知识点: 1. **Python基础*...

    豆瓣读书爬虫,保存到excel中(2021.6.28可用)

    标题中的“豆瓣读书爬虫,保存到excel中”意味着这个项目是关于编写一个网络爬虫程序,该程序能够从豆瓣读书网站抓取数据,并将抓取的信息存储到Excel电子表格中。这种爬虫通常用于数据分析、图书推荐系统或个人爱好...

Global site tag (gtag.js) - Google Analytics