微信号:we21cto

介绍:21CTO(21CTO.com)是中国项级技术专家的学习与服务平台.我们为CTO、技术总监、架构师等技术专家提供高质量的资讯、问答、活动等产品,同时与企业连接,提供技术咨询、研发、运维、技术支持、培训及人才招聘等服...

个性化推荐系统架构设计(三)— 使用爬虫抓取网页与RSS内容

2016-11-20 12:22 21CTO

故事越来越有意思。当然开发爬虫抓取工作没有想像的那么容易,但是一切事物都是从简单到复杂,再从复杂回归到事物本身。下面我们就开始准备好锤子,斧子,铅笔刀啥的,开始进行抓取工作。

 

爬虫,按照获取内容的不同。可以分为大爬虫和小爬虫。有诸多开源产品,比如Storm Crawler,Elastics Search,Lucence,Sphinx等,这些都是用来抓取和索引全网站,之后根据所抓取的内容做全文检索。

 

大者说来百度,Google也莫过如此,因为抓取的数据量存储量大,要花费数亿元建立自己的IDC,包括一个大的分布式Web存储集群。

用户搜索时,一个关键字,是通过负载均衡到后端数十万台服务器后消化的无影无踪。



万丈高楼平地起。Google的两位创始人94在起家的时候也只有两台旧服务器。一个合格Crawler架构要达到的特性大概有如下:

 

1、鲁棒性

防止蜘蛛陷阱。当全站抓取,当页面存在外部链接,重复时会形成循环。当目标网站不可用时,适当放下,待恢复时第一时间进行采集。

 

2、礼貌

哪些页面可以抓取,哪些不能。当有隐私的内容与版权的问题,不进行采集。

 

3、质量

采集及时有效。新鲜的内容才更有价值。

 

4、可视化

可视化包括抓取采集过程中,能够实时监控状态;

另一侧的可视化为数据的整理清洗后的可视化。

 

5、可扩展

支持计划任务,分布式,代理服务器,模仿用户登录,自定义宏。

 

我们要做新闻资讯的推荐,抓取的是新闻,并非全站。Crawler不必做得像搜索引擎一样把页面全部抓取,然后分析,索引。而是按需取用,拿页面某些内容即可。

 

可以通过两种方式来采集网站的内容。

 

RSS与ATOM源

 

RSS与ATOM从网景时代发展到现在。在国外每家新闻网站基本都做了标配,用户订阅后,每天会根据RSS来查看有哪些内容做了更新。

 

RSS是一个XML文件格式,用来描述当前网站频道更新了哪些内容,它是一个新闻列表,包括标题和部分内容。

想必你也看到了,这是techcrunch网站的RSS源,包括RSS格式与ATOM两种格式。


它告诉我们最后更新的时间,以及更新文章的条数,包括发布日期时间、简介、图片地址等。


TC网站RSS的URL地址是:https://techcrunch.com/feed/。从源代码中看得出,这是由WordPress搭建的平台。

对于爬虫开,可以把RSS当做方网站的开放API,在技RSS内容,取得标题介,再根据超链接取得详细内容。

 

对于国内,一些网站并没有RSS,或者不及时更新,这属于大多数情况。我们可以模拟成各种浏览器,根据内容定制化抓取。

 

数据源与定制化抓取



知已知彼,百战不贻。在对一个目标网站分析之前,先了解一下对方用的什么技术来开发的网站。

 

使用PHP的get_headers()或curl都可以取到对方服务器的头信息,除非对方有意隐藏掉。

 

知道对方服务器的信息,可以知道响应如404,500,200等HTTP状态,根据服务器的技术栈来做补充策略。

 

一些网站,特别是新闻类网站,为了防止采集,做了很多混淆工作,比如使用Ajax,用JavaSript来输出html片断等。

 

在移动互联网时代,很多站点都建有面向手机的网站,如http://m.sina.com.cn,手机端的网站标签简洁,更方便我们分析抓取。有的网站设置了只有微信等特定浏览器查看,可以模仿wechat等用户代理的方法来采集。类似于如下代码:


$header[] =  'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';

$header[] =  'Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3';

//设置为微信浏览器

if($is_wechat  == 1){

    $header[] = "User-Agent: Mozilla/5.0  (iPhone; CPU iPhone OS 6_1_2 like Mac OS X) AppleWebKit/536.26 (KHTML, like  Gecko) Mobile/10B146 MicroMessenger/5.0";

}else{

    $header[] = 'User-Agent: Mozilla/5.0  (Windows NT 5.2; rv:25.0) Gecko/20100101 Firefox/25.2';

}

    $header[] = 'Host: ' . $aurl['host'];

    $header[] = 'Connection: Keep-Alive';

    $header[] = 'Cookie:  tracknick=\u590F\u6587\u8F69';


 

以上,我们通过几种方法,可以正常拿到网页内容了。

分析和抓取列表页

列表页一般为标题,简介,缩略图之类。比如一个房源列表的页面。我们通过正则表达式进行内容提取。


preg_match_all("/<ul  class=\"attr_info fang fang_new\">(.*)<\/ul>/siU",  $house_details, $house_info);

//提取联系人,电话

preg_match_all("/<p  class=\"llname\">(.*)<\/p>/siU", $house_details,  $contact_personal);

preg_match_all("/<p  class=\"llnumber\">(.*)<\/p>/siU", $house_details,  $contact_number);

//提取图片路径

preg_match_all("/<div  class=\"image_area image_area_new\">(.*)<\/div>/siU",$house_details,  $house_images);

preg_match_all('/ref="(.*?)\"/s',$house_images[1][0],  $house_image);           

foreach($house_image[1]  as $img){

    echo $img ."<br />";

}

 

类似于上面代码,可以顺着列表页的页码,列表页的列表内容,按照链接取得详细链接,进行批量采集。

 

抽取详细页的内容,可以使用正则表达式,也可使用SimpleXML/DomDocument中的xPath方法。有的页面会嵌入多个HTML,导致DOM不完整,使用正则表达式会更靠谱。当HTML是已知完整的片断,使用xPath当然没问题,效率也更高。

 

使用并发下载可以curl_muiti处理,可以参照《PHP与MySQL高性能应用开发》一书介绍,后续文章我会和大家再延伸介绍。

 

小结


本文给大家介绍了爬虫开发的策略与实践技巧。使用本文的部分技术,你可以进行一个Crawler的开发。

后续我会继续讲解完整的实践。下篇内容介绍:

  • 使用cookie或session抓取实践

  • RSS抓取实践。

  • 监控来源是否更新

  • 定制化抓取与去重

  • 入库与清理

  • crawler的管理。

 

作者:杜江。21CTO(21cto.com)社区创始人。多年架构与管理经验。 著有《PHP5与MySQL5 Web开发技术详解》、《PHP5完全攻略》、《PHP与MySQL高性能应用开发》(机械工业出版社出版,各电商平台和书店有售) 

 
21CTO 更多文章 个性化推荐系统(三)— 构建爬虫开发函数基础库 个性化推荐系统(三)— 构建爬虫开发函数基础库 个性化推荐系统架构设计(二):爬虫系统概述 个性化推荐系统架构设计(一) 程序猿怎么跳出技术的“鄙视链”
猜您喜欢 AndroidProgrammer赞赏功能 盗亦有道的另类解读 哇~学费减免2000元啦~⊙0⊙~ 除了直播吃饭,终于有直播程序员写代码的了 Android开发人员应避免的10个误区