社会化海量数据采集爬虫框架搭建

社会化海量数据采集爬虫框架搭建css

随着BIG DATA大数据概念逐渐升温,如何搭建一个可以采集海量数据的架构体系摆在你们眼前。如何可以作到所见即所得的无阻拦式采集、如何快速把不规则页面结构化并存储、如何知足愈来愈多的数据采集还要在有限时间内采集。这篇文章结合咱们自身项目经验谈一下。html

咱们来看一下做为人是怎么获取网页数据的呢?java

一、打开浏览器,输入网址url访问页面内容。
二、复制页面内容的标题、做者、内容。
三、存储到文本文件或者excel。mysql

从技术角度来讲整个过程主要为 网络访问、扣取结构化数据、存储。咱们看一下用java程序如何来实现这一过程。web

import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang.StringUtils;

public class HttpCrawler {
       public static void main(String[] args) {

            String content = null ;
             try {
                  HttpClient httpClient = new HttpClient();
                   //一、网络请求
                  GetMethod method = new GetMethod("http://www.baidu.com" );
                   int statusCode = httpClient.executeMethod(method);
                   if (statusCode == HttpStatus. SC_OK) {
                        content = method.getResponseBodyAsString();
                         //结构化扣取
                        String title = StringUtils.substringBetween(content, "<title>" , "</title>" );
                         //存储
                        System. out .println(title);
                  }

            } catch (HttpException e) {
                  e.printStackTrace();
            } catch (IOException e) {
                  e.printStackTrace();
            } finally {
            }
      }
}

经过这个例子,咱们看到经过httpclient获取数据,经过字符串操做扣取标题内容,而后经过system.out输出内容。你们是否是感受作 一个爬虫也仍是蛮简单呢。这是一个基本的入门例子,咱们再详细介绍怎么一步一步构建一个分布式的适用于海量数据采集的爬虫框架。ajax

整个框架应该包含如下部分,资源管理、反监控管理、抓取管理、监控管理。看一下整个框架的架构图:正则表达式

社会化海量数据抓取组件图

    • 资源管理指网站分类体系、网站、网站访问url等基本资源的管理维护;
    • 反监控管理指被访问网站(特别是社会化媒体)会禁止爬虫访问,怎么让他们不能监控到咱们的访问时爬虫软件,这就是反监控机制了;算法

一个好的采集框架,无论咱们的目标数据在哪儿,只要用户可以看到都应该能采集到。所见即所得的无阻拦式采集,不管是否须要登陆的数据都可以顺利采集。如今 大部分社交网站都须要登陆,为了应对登陆的网站要有模拟用户登陆的爬虫系统,才能正常获取数据。不过社会化网站都但愿本身造成一个闭环,不肯意把数据放到 站外,这种系统也不会像新闻等内容那么开放的让人获取。这些社会化网站大部分会采起一些限制防止机器人爬虫系统爬取数据,通常一个帐号爬取不了多久就会被 检测出来被禁止访问了。那是否是咱们就不能爬取这些网站的数据呢?确定不是这样的,只要社会化网站不关闭网页访问,正常人可以访问的数据,咱们也能访问。 说到底就是模拟人的正常行为操做,专业一点叫“反监控”。sql

那通常网站会有什么限制呢?chrome

必定时间内单IP访问次数,没有哪一个人会在一段持续时间内过快访问,除非是随意的点着玩,持续时间也不会太长。能够采用大量不规则代理IP来模拟。

必定时间内单帐号访问次数,这个同上,正常人不会这么操做。能够采用大量行为正常的帐号,行为正常就是普通人怎么在社交网站上操做,若是一我的一天24小时都在访问一个数据接口那就有多是机器人了。

若是能把帐号和IP的访问策略控制好了,基本能够解决这个问题了。固然对方网站也会有运维会调整策略,说到底这是一个战争,躲在电脑屏幕后的敌我双方,爬 虫必需要能感知到对方的反监控策略进行了调整,通知管理员及时处理。将来比较理想应该是经过机器学习算法自动完成策略调整,保证抓取不间断。

    • 抓取管理指经过url,结合资源、反监控抓取数据并存储;咱们如今大部分爬虫系统,不少都须要本身设定正则表 达式,或者使用htmlparser、jsoup等软件来硬编码解决结构化抓取的问题。不过你们在作爬虫也会发现,若是爬取一个网站就去开发一个类,在规 模小的时候还能够接受,若是须要抓取的网站成千上万,那咱们不是要开发成百上千的类。为此咱们开发了一个通用的抓取类,能够经过参数驱动内部逻辑调度。比 如咱们在参数里指定抓取新浪微博,抓取机器就会调度新浪微博网页扣取规则抓取节点数据,调用存储规则存储数据,无论什么类型最后都调用同一个类来处理。对 于咱们用户只须要设置抓取规则,相应的后续处理就交给抓取平台了。

整个抓取使用了 xpath、正则表达式、消息中间件、多线程调度框架(参考)。xpath 是一种结构化网页元素选择器,支持列表和单节点数据获取,他的好处能够支持规整网页数据抓取。咱们使用的是google插件 XPath Helper,这个玩意能够支持在网页点击元素生成xpath,就省去了本身去查找xpath的功夫,也便于将来作到所点即所得的功能。正则表达式补充xpath抓取不到的数据,还能够过滤一些特殊字符。消息中间件,起到抓取任务中间转发的目的,避免抓取和各个需求方耦合。好比各个业务系统均可能抓取数据,只须要向消息中间件发送一个抓取指令,抓取平台抓完了会返回一条消息给消息中间件,业务系统在从消息中间件收到消息反馈,整个抓取完成。多线程调度框架以前提到过,咱们的抓取平台不可能在同一时刻只抓一个消息的任务;也不可能无限制抓取,这样资源会耗尽,致使恶性循环。这就须要使用多线程调度框架来调度多线程任务并行抓取,而且任务的数量,保证资源的消耗正常。

无论怎么模拟总仍是会有异常的,这就须要有个异常处理模块,有些网站访问一段时间须要输入验证码,若是不处理后续永远返回不了正确数据。咱们须要有机制能 够处理像验证码这类异常,简单就是有验证码了人为去输入,高级一些能够破解验证码识别算法实现自动输入验证码的目的。

扩展一下 :所见即所得咱们是否是真的作到?规则配置也是个重复的大任务?重复网页如何不抓取?

一、有些网站利用js生成网页内容,直接查看源代码是一堆js。 可使用mozilla、webkit等能够解析浏览器的工具包解析js、ajax,不过速度会有点慢。
二、网页里有一些css隐藏的文字。使用工具包把css隐藏文字去掉。
三、图片flash信息。 若是是图片中文字识别,这个比较好处理,可以使用ocr识别文字就行,若是是flash目前只能存储整个url。
四、一个网页有多个网页结构。若是只有一套抓取规则确定不行的,须要多个规则配合抓取。
五、html不完整,不完整就不能按照正常模式去扣取。这个时候用xpath确定解析不了,咱们能够先用htmlcleaner清洗网页后再解析。
六、 若是网站多起来,规则配置这个工做量也会很是大。如何帮助系统快速生成规则呢?首先能够配置规 则能够经过可视化配置,好比用户在看到的网页想对它抓取数据,只须要拉开插件点击须要的地方,规则就自动生成好了。另在量比较大的时候可视化仍是不够的, 能够先将类型相同的网站归类,再经过抓取的一些内容聚类,能够统计学、可视化抓取把内容扣取出几个版本给用户去纠正,最后确认的规则就是新网站的规则。这 些算法后续再讲。这块再补充一下(多谢zicjin建议):

背景:若是咱们须要抓取的网站不少,那若是靠可视化配置须要耗费大量的人力,这是个成本。而且这个交给不懂 html的业务去配置准确性值得考量,因此最后仍是须要技术作不少事情。那咱们可否经过技术手段能够帮助生成规则减小人力成本,或者帮助不懂技术的业务准 确的把数据扣取下来并大量复制。

方案:先对网站分类,好比分为新闻、论坛、视频等,这一类网站的网页结构是相似的。在业务打开须要扣取的尚未录 入咱们规则库的网页时,他先设定这个页面的分类(固然这个也能够机器预先判断,他们来选择,这一步必需要人判断下),有了分类后,咱们会经过“统计学、可 视化判断”识别这一分类的字段规则,可是这个是机器识别的规则,可能不许确,机器识别完后,还须要人在判断一下。判断完成后,最后造成规则才是新网站的规 则

七、对付重复的网页,若是重复抓取会浪费资源,若是不抓须要一个海量的去重判断缓存。判断抓不抓,抓了后存不存,而且这个缓存须要快速读写。常见的作法有bloomfilter、类似度聚合、分类海明距离判断。

  • 监控管理指无论什么系统均可能出问题,若是对方服务器宕机、网页改版、更换地址等咱们须要第一时间知道,这时监控系统就起到出现了问题及时发现并通知联系人。

目前这样的框架搭建起来基本能够解决大量的抓取需求了。经过界面能够管理资源、反监控规则、网页扣取规则、消息中间件状态、数据监控图表,而且能够经过后 台调整资源分配并能动态更新保证抓取不断电。不过若是一个任务的处理特别大,可能须要抓取24个小时或者几天。好比咱们要抓取一条微博的转发,这个转发是 30w,那若是每页线性去抓取耗时确定是很是慢了,若是能把这30w拆分不少小任务,那咱们的并行计算能力就会提升不少。不得不提的就是把大型的抓取任务 hadoop化,废话不说直接上图:

社会化海量数据抓取组件图

今天先写到这里,后续再介绍下 日均千万大型采集项目实战。

 

 

提到如何搭建一个社会化采集系统架构,讲架构通常都比较虚,这一篇讲一下如何实战用低成本服务器作到日流水千万级数据的分布式采集系统。

有这样一个采集系统的需求,达成指标: 须要采集30万关键词的数据 、微博必须在一个小时采集到、覆盖四大微博(新浪微博、腾讯微博、网易微博、搜狐微博)。为了节约客户成本,硬件为普通服务器:E5200 双核 2.5G cpu, 4 G DDR3 1333内存,硬盘 500G SATA 7200转硬盘。数据库为mysql。在这样的条件下咱们可否实现这个系统目标?固然若是有更好的硬件不是这个文章阐述的内容。现经过采集、存储来讲明一下如何实现:

1、采集,目标是在一个小时内把30万关键词对应的数据从四大微博采集下来,可以使用的机器配置就是上面配置的普通服务器。采集服务器对硬盘没有太多要求,属于cpu密集型运算,需耗费一些内存。评估下来硬件资源不是瓶颈,看下获取数据的接口有什么问题?

  • 一、经过各大微博的搜索api。就好比新浪微博API针对一个服务器IP的请求次数,普通权限限制是一个小时1w次,最高权限合做受权一个小时 4w次。使用应用时还须要有足够的用户,单用户每一个应用每小时访问1000次,最高权限4w次须要40个用户使用你的应用。达到30w关键词,至少须要8 个应用,若是每一个关键词须要访问3页,总共须要24个合做权限的应用。实际操做咱们是不可能为这个项目作到开发24个合做权限的应用,因此这个方式不是很 合适。新浪微博API限制参考连接
  • 二、经过各大微博的最新微博收集数据,微博刚推出的时候,各大微博都有微博广场,能够把最新的微博都收集下来,而后经过分词,若是出现了30万关 键词中的一个就留下,其余就丢弃掉。不过如今除了腾讯微博和搜狐微博有微博广场相似的功能,新浪微博和网易微博已经没有这项功能了。另按照新浪微博以前公 布的数据,注册用户已经超过5亿,每小时超过1亿条微博,若是全量采集对数据存储是个大的考验,也须要大量的系统资源,实际采集了一亿条,也许就1000w条有用,浪费了9000w条数据的资源。
  • 三、经过各大微博的网页搜索,可见便可抓的方式,结合反监控系统模块模拟人的正常行为操做,搜索30万关键词数据,使资源最大化利用。为了保证在 一个小时采集到,须要采用分布式多线程模式抓取,并发采集。并发的时候不能从同一个ip或者同一个ip网段出去,保证对方不会监测到咱们的爬虫。

咱们最后采用了第三种方式,目前运行情况为经过30w关键词搜索获得的全部微博加在一块儿总量1000多w条天天,新浪和腾讯最多,新浪微博略胜一筹。使用了6台普通PC服务器,就算一台机器7000元,总共4万元硬件设备解决采集硬件问题。总体部署图为:

milioncrawler1 (1)

2、存储,采集下来的数据如何处理?首先存储采集数据是个密集写的操做,普通硬盘是否可以支持,mysql数据库软件可否支持,将来量忽然增长如何应对?再就是评估存储空间,天天增量这么多须要耗费大量的存储资源,如何存放而且易扩展。

    • 一、如何存储。正常来讲咱们上面配置的服务器,mysql使用myisam引擎一张表最多20w,使用 innodb引擎最多400w,若是超过这个数量,查询更新速度奇慢。这里咱们采用一个比较取巧的作法,使用mysql的innodb存储引擎作了一层缓 存库,这个缓存库有两个缓存表,每一个表只存储少于300w的数据,有一张表多于300w的数据就切换到另外一张表插入直到超过300w再切换回去。切换成功 后,把多于300w数据的表truncate掉,记得必定要没有数据插入的时候再truncate,防止数据丢失。这里必定要用truncate,不能使 用delete,由于delete须要查询,要用到索引读写,而且delete还会写数据库log耗费磁盘IO,存储空间也没有释放。truncate和 drop是操做数据库删除数据比较好的作法。因为有两个表做为数据插入表,使用数据库表的自增id并不太合适,须要一个高速的惟一自增Id服务器提供生成 分布式ID。另数据库彻底能够关闭写事务日志 ,提升性能,由于抓取的数据当时丢失再启动抓取就能够了, 这样数据库能够保持在一个比较高性能的状况完成插入操做。抓取缓存表结果如图:

milioncrawler2

    • 二、存储空间。插入后的数据须要保存下来,不能在超过300w后被truncate掉了。咱们须要有个程序在 达到300万时被truncate掉以前把数据同步走,存放到另一个库上(咱们叫作结果库,结果库也是使用innodb引擎)。不过咱们天天采集的数据 1000多万,按天递增,mysql一张表一天就撑爆了,咱们这个表不是写操做密集型,因此结果库能够存储多点数据,设定上限500w,可是500万仍是 存不下1000万数据。咱们须要对mysql最终结果分库分表。将数据先按照时间分机器分库,再按照数据源分表,好比201301经过hash计算的数据 存放在一个机器,201302经过hash计算在另外一个机器。到了机器后再按照天或者半天分表,好比表名为 weibo_2013020101 、weibo_2013020112。weibo_2013020101表示2月1日上午一个表,weibo_2013020112表示2月1日下午一个 表。光这样分了仍是不够,1000w/2=500w,经不起压力扩展。咱们还须要把表再拆分,好比weibo_2013020101 拆成 weibo_2013020101_1(新浪微博)、weibo_2013020101_2(腾讯微博)、weibo_2013020101_3(网易微 博)、weibo_2013020101_4(搜狐微博)。这样一张表平均就存放 500w/4 = 125w 条数据,远远小于500w上限,还能够应对将来突发的增加。再从存储空间来算,就算一条微博数据为1k,一天 1000w*1k=10G,硬盘500G最多存放50天的数据,因此咱们规划机器的时候能够挂接多一点硬盘,或者增长机器。结果库分表如图:

milioncrawler3

按照这样的架构,咱们使用开源免费软件、低成本服务器搭建的千万级数据采集系统在生产运转良好。

相关文章
相关标签/搜索