首页 > 其他 > 详细

【机器人系列】爬取携程产品图片式价格

时间:2015-03-26 21:00:46      阅读:224      评论:0      收藏:0      [点我收藏+]

携程旅行网是国内最大的在线旅游提供商,其价格为了防止爬虫,是用了图片形式,从而防爬。 据我所“爬”,美团最近也开始使用图片形式的价格。但是这种图片说白了其实是自欺欺人,防君子不防小人(应该是防菜鸟不防高手才对技术分享)。今天,咱们就来看看,如何破解携程的图片式价格。

先上一张图,看看这个价格是怎么来的。

技术分享

可以看到,这个数字5,是由p_h57_7这个CSS样式定义的。而这个样式里定义了一个背景图片,注意这个地方后面跟了一个数字! 也就是 -1346。 看看这个图片是啥样的~

技术分享

真实的图片比这个要长,我截取了一段。这时候你可能联想到了,上面的1346这个数字可能就是代表了这张图片横向第1346个像素所代表的数字。确实如此。不过这个位置的像素都是白色,真正的数字从往后两个像素开始,也就是1348这个项目开始。这个像素处的数字正是5。

下面就是图像处理啦! 听起来图像处理特别高大上。其实咱们这里用到的图像处理特别简单。为啥? 虽然背景图像是会经常动态更新的,但是因为这些数字都是一样的格式。比如3这个数字,同一个尺寸的背景图中的3,都是一样的。那可能又要问了,为啥不弄成不一样呢? 因为这是价格。总不能弄成验证码那样扭曲的吧,会被投诉的。

关于解决方案,就像标题里说的,这是一个爬取操作,属于一个爬虫,对于互联网海量的数据,咱们要求爬虫:快,准,狠!快字当先。所以我们要用最快的处理算法来识别每一个数字。如果你像用图像识别用的那些统计学理论成果来做这件事,那爬完所有数据所用的时间将非常恐怖。

像前面所说,这些字符一共就12个,分别是: . , 0 1 2 3 4 5 6 7 8 9

我们来放大两个数字:3和4。

技术分享 技术分享      


看他们的第一竖列,是不同的。所以可以根据第一竖列来区分3和4。其他的数字也都一样。

为了加快速度,我们要先对图片做2值化处理,即只要这个像素不是白色,就全部设置为1,是白色就设置为0. 在代码中,我们使用了boolean数组来存储2值化结果。然后从第一竖列开始,形成一颗决策树。比如,若某两个字符的第一竖列一样,那么就继续判断第二竖列,以此类推,只要两个字符不一样,肯定会有不一样的竖列。这样可以尽早发现数字。

以下是识别算法代码:

/** 获取图片像素的二值化二维数组——纵向优先, 为true就是该点为白色,为false该点为黑色
	 * @param img
	 * @return
	 */
	public static boolean [][] get2ValuePixesHeightFirst(BufferedImage img)
	{
		int width= img.getWidth();
		int height= img.getHeight();
		boolean [][] result = new boolean[width][height];
		for(int i=0;i<width;i++)
			for(int j=0;j<height;j++)
			{
				//透明(在RGB中为黑色)和白色 都设置为false;
				result[i][j]=img.getRGB(i, j)==16777215 || img.getRGB(i, j)== 0?false:true;
			}
		return result;
	}
	
	// (-1) 空白 
	//(-2)stopSymbol   16 17 18
	//(-3)comma                 19 20 21 22
	// 1          8 9  17 18
	// 2      6 7 8 9       16 17 18
	// 3      6 7 8 9    15 16 17 18
	// 4          12 13 14 15      
	// 5                 15 16 17 18
	// 6            9 10 11 12 13 14 15 16
	// 7      6 7      17 18
	// 8        7 8 9 10 11  13 14 15 16 17
	// 9          8 9 10 11 12 13
	// 0          8 9 10 11 12 13 14 15 16
	
	
	/** 判断是否为空白竖列
	 * @param verticalLineArray
	 * @return
	 * @throws Exception
	 */
	public static boolean isBlankLine(boolean [] verticalLineArray) throws Exception
	{
		if(verticalLineArray.length!=22)
		{
			throw new Exception("This is a new rule image. Can not recognize it!");
		}
		for(int i=0;i<verticalLineArray.length;i++)
		{
			if(verticalLineArray[i])
			{
				return false;
			}
		}
		return true;
	}
	
	/** 识别数字
	 * @param verticalLineArray
	 * @return
	 * @throws Exception
	 */
	public static char recognizeNumber( boolean [] verticalLineArray) throws Exception
	{
		if(verticalLineArray.length!=22)
		{
			throw new Exception("This is a new rule image. Can not recognize it!");
		}
		if(verticalLineArray[6-1])
		{// 2 , 3,  7
			if(verticalLineArray[8-1])
			{// 2, 3
				if(verticalLineArray[15-1])
				{//3
					return '3';
				}
				else
				{
					return '2';
				}
			}
			else
			{// 7
				return '7';
			}
		}
		else
		{
			if(verticalLineArray[7-1])
			{//8
				return '8';
			}
			else
			{
				if(verticalLineArray[8-1])
				{//1 , 9 , 0
					if(verticalLineArray[10-1])
					{//9 , 0
						if(verticalLineArray[14-1])
						{
							return '0';
						}
						else
						{
							return '9';
						}
					}
					else
					{
						return '1';
					}
				}
				else
				{
					if(verticalLineArray[9-1])
					{// 6
						return '6';
					}
					else
					{// 4 ,5 , '.' , ','
						if(verticalLineArray[12-1])
						{// 4
							return '4';
						}
						else
						{
							if(verticalLineArray[15-1])
							{
								return '5';
							}
							else
							{
								if(verticalLineArray[16-1])
								{
									return '.';
								}
								else if(verticalLineArray[19-1])
								{
									return ',';
								}
								else
								{
									return '\0';
								}
							}
						}
					}
				}
			}
		}
			
	}
识别速度和效果:

技术分享

技术分享

处理整个一张图片需要8ms(以后所有相同的图片不需要重复处理(可以放在缓存中间件中))。

下次读取,只需要0ms,几乎不花时间。


源码下载:https://github.com/tbwork/Ctrip_price_recognizer

【机器人系列】爬取携程产品图片式价格

原文:http://blog.csdn.net/tbwood/article/details/44652195

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!