爬取搜狐几十万新闻数据——一些见解与感悟

因为负责一个新闻推荐系统的项目,需要采集大量的新闻数据作为文本分类的材料,通过自己的不断摸索,以知乎上某位大牛的框架为基础,完成了一个能采集几十万新闻数据的爬虫,并且健壮性非常强。仅以此文,将自己收获的见解与一些容易入的坑与大家分享。

开始

其实写爬虫的时候有个原则,如果该网站存在手机版本的网站,那么我们应该去爬取手机端的网站。为什么呢?看下面两张搜狐新闻pc网页版本和手机网页版本的图就明白了:

PC版网页


手机版搜狐新闻

 明显可以看到手机搜狐端的结构要比pc网页端的清晰,这样有利于我们分析网页的结构和提取重要的数据(还有一个原因是手机端比pc端的反爬虫措施要弱一点),因此我们应该选择手机端网页开始我们的分析。下一步,我们分析一下我们的入口url地址。由于我需要采集像体育,军事,娱乐等各个类别的新闻,在我第一次进行爬取的时候,其实手机搜狐网的网页结构每一级还是更加清晰工整的,非常有利于我进行大规模爬取的,第一次时候的做法是按三级结构依次进行爬取。如下图:

爬取顺序

时隔几月,当我再次打开手机搜狐准备爬取的时候,发现页面结构有变化,按老方法做可能容易引入更多的噪声且解析起来更麻烦了。因此想着该升级一下方法了。

对付分级结构不明显的网站的时候,只能想到上BFS和DFS了(但是这样就给我带了一个弊端,后面在说)。我这次采用了BFS的思路,在页面解析出我们需要的有特征的的URL,然后放入一个阻塞队列,然后依次从阻塞队列里面取url,如此反复不断的进行。

但是入口地址不用变,打开手机搜狐拉到最底下有个导航,点进去之后可以看到有很全的类目,把这些地址抓下来作为队列里的初始url。


类别入口

那我们这次就要分析一下拥有新闻正文内容的新闻url有什么特点,通过观察可以很容易的发现它的特点。

有新闻正文内容的URL

反之,我们不需要要的一些网页的url,可以看一些例子——

                          新闻是图片形式的网页url :  https://m.sohu.com/p/783590/

                          小说内容的网页url : read.m.sohu.com/book/1212604/

总之,我们如果要文字内容的新闻,只要去匹配  http://m.sohu.comm/n/(此处是一串数字)/ 的特征的url就可以了,另外,我们发现像财经,体育这些类别入口的url是这样的——“https://m.sohu.com/c/5100/”,“https://m.sohu.com/c/5/”,“https://m.sohu.com/c/8/”。

所以说,不同内容和类别的网页url是有特征的,我们应根据自己的需要进行分析取舍。回到我的项目的需要,我在爬虫处理的时候,只爬取符合正则表达式http://m.sohu.com/n/[0-9]+/ 和 https://m.sohu.com/c/[0-9]+/的网页URL,把他们扔进队列,并且,如果是 http://m.sohu.com/n/[0-9]+/ 形式的url,我们知道存在我们需要的新闻正文内容,那么我们还要解析出我们需要的内容,否则,拿到类别入口URL的时候,先扔进队列里,等一下从队列里取出的时候再往深了爬。

下一步,拿到了有新闻内容的url,我们就该对我们要提取的内容做一下页面分析了。学爬虫的都知道用正则表达式来提取我们需要的内容,但你也应该知道了,用正则提取的鲁棒性实在不敢恭维,而且它又巨不好写,巨复杂(尽管它效率应该是最高的,任何事物都有两面性嘛)。所以我强烈推荐用css选择器或xpath的语法,配合java中的Jsoup使用简直是神器(python中有Beatifulsoup),而且它们语法简单,容易上手,定位准确,鲁棒性强。而且,在页面中检查一个元素的时候,点击右键直接可以获得它的css路径或者xpath路径。


只不过拷贝下来的路径,一般是不能直接用的,像一段新闻的内容都是用一个p标签括起来,比如  body > section.article-wrapper > article > p:nth-child(3),这样得到的是一个绝对路径,也就是你抽取内容的时候是精确的定位到这一段,如果要获得整个新闻的内容,就要获取所有同级路径下的p标签的内容然后加起来。

 因此,必要的css和xpath语法还是要掌握,然后根据需要进行灵活组合使用。

在爬取的过程中,有一部分页面有异步加载的情况,需要点击展开剩余那个元素才能得到所有内容,这种情况其实好处理,但是我在第二次爬的时候手机搜狐又改版了。第一次,剩余的内容还真不在现在的页面里,需要我们重新发http请求去获取剩余内容,返回的是一个json字符串(如何知道请求的地址?跟上面分析url特征一样,只要先F12开启控制台,点击network,然后再去点展开剩余的标签,它就会向服务器发请求,多试几个,就能找到url的特征)。但是第二次的时候,其实剩余的内容已经在现在的页面中了,只是没展开,这样就更好办了,用同样的抽取内容的方法就能直接得到我们想要的了。


异步加载页面

以上就是从分析到获取我们想要的内容的一个过程。如此只是实现了基本功能,如何构造一只健壮的爬虫呢?如何判断url有没有重掉呢?爬虫万一被封了怎么办?

 对于鲁棒性来说,可以说就算使用了css筛选器和xpath语法也不能保证完全不在解析的时候出问题,我的办法是,尽量在定位元素和解析内容的时候多用 try catch 语句或者if else 语句,把所有有可能出现异常的地方都做异常处理。否则,就像我当时那样,报各种数组越界等异常。

去重算法的话知乎大神采用的是强大的bloomFilter算法,可以在海量数据的情况下依旧很高效的对字符串判重,原理就是四个hash函数的叠加使用。要了解的朋友可以自行上网搜索。

可以说,短时间内对同一个目标网站进行大量的请求肯定会被服务器封IP,那么我们想到的自然就是不断的换IP,有很多可用的提供代理IP的网站。针对这个问题,我还专门写了个miniSpider,在爬取代理IP的同时对该代理IP进行测试,因为不是所有的代理IP地址在我们的程序里换IP之后都是可用的,所以确认测试可用之后再存储到本地文件。测试IP是否可用的网址是 : http://ip.chinaz.com/getip.aspx 。

当然,要提高效率,就少不了多线程(想想一只蜘蛛和十只蜘蛛同时工作时效率的区别) 。多线程可以用一个线程池来维护,同时,再开启另一个监视线程池线程数量的线程,如果监测到线程池里的线程数少于一定数目了,就重新建立几个线程。如此,爬虫挂着几天几夜基本都挂不了了。

当然,如果你想暂停一下爬虫之后开启的时候爬取新闻URL仍能不重复,那么你可以把储存url队列的数据结构通过序列化的方式存储到本地,每次开启的时候再自动读入。

最终,我的爬虫爬了一个晚上之后,总共爬了40w来条新闻数据,但是后期检查的时候,发现严重的类别不平衡,某类别下的新闻总共有10w多条而其中一个类别却只有可怜的几百条。这样对我后期用来训练文本分类也会产生影响。原因也好理解,同一个类别的url在队列里总是凑在一块的,如果前面的队列没爬完的话,后面的就根本没机会。解决的办法现在想到的就是随机打乱队列,不过我还没去实现。


部分数据截图

结语

其实写好爬虫是一个阶段性的过程,最重要的还是先掌握好http和html的知识。写爬虫并不要求熟练会写html,但是一定得看得懂。刚开始的时候不熟练,练得多了,也就是信手拈来的事情。

关于代码,下次我上传Github之后再来分享。

-------------------------------------------------------------------------------

2017.5.2 更新

      代码地址 : https://github.com/JetFeng/SohuSpider-Java

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容