网页新闻抓取(一个新闻pc网页版本和手机网页端的新闻数据的爬虫)

优采云 发布时间: 2021-12-29 14:13

  网页新闻抓取(一个新闻pc网页版本和手机网页端的新闻数据的爬虫)

  因为负责一个新闻推荐系统项目,需要采集

大量的新闻数据作为文本分类素材。通过自己的不断探索,基于知乎上某大牛的框架,完成了一个可以采集数十万条新闻数据的项目。爬虫,鲁棒性很强。就在这篇文章中,我将我所获得的见解和一些简单的坑分享给大家。

  开始

  其实写爬虫是有原则的。如果有移动版的网站,那么我们应该抓取移动版的网站。为什么?看下面搜狐新闻pc网页版和手机网页版的两张图就明白了:

  

  PC版网页

  

  搜狐新闻手机

  很明显我们可以看到手机搜狐端的结构比PC端的web端更清晰,这有助于我们分析网页的结构和提取重要数据(另一个原因是手机端是比PC端的反爬虫措施弱),所以我们应该选择手机网页开始我们的分析。接下来,我们分析我们的入口 URL 地址。由于我需要采集

体育、军事、娱乐等各个类别的新闻,所以在我第一次爬的时候,其实手机搜狐的页面结构在各个层面都更加清晰整洁,这对于我进行*敏*感*词*。对于爬取,第一次的方法是按照三层结构爬取。如下所示:

  

  抓取订单

  几个月后,当我再次打开手机搜狐准备抓取时,发现页面结构发生了变化。遵循旧方法可能容易引入更多噪声并使分析更加麻烦。所以我认为是时候升级方法了。

  在处理层次结构不明显的网站时,我只能想到BFS和DFS(但这给我带来了一个缺点,我稍后会讲到)。这次采用了BFS的思路,在页面上解析出我们需要的特征URL,放入阻塞队列,然后依次从阻塞队列中取出URL,以此类推。

  但是入口地址不需要改变。打开手机搜狐,拉到导航底部。点进去后,可以看到分类很多。获取这些地址作为队列中的初始 url。

  

  分类条目

  那么我们这次就用新闻正文内容来分析新闻url的特征,通过观察我们可以很容易的发现它们的特征。

  

  收录

新闻正文内容的 URL

  相反,我们不需要一些网页的网址,你可以看一些例子——

  新闻是图片形式的网页网址:

  小说内容网页地址:/book/1212604/

  简而言之,如果我们想要有文字内容的新闻,只需要匹配(这里是一串数字)/特征URL即可。另外,我们发*敏*感*词*融、体育等品类的入口网址是这样的——""、""、""。

  因此,不同内容和类别的网址都有各自的特点,我们应该根据自己的需要进行分析和选择。回到我项目的需求,我在处理爬虫的时候,只爬取了符合正则表达式[0-9]+/和[0-9]+/的网页的url,扔进队列,如果是[0-9]+/形式的URL。我们知道有我们需要的新闻正文内容,那么我们就要解析出我们需要的内容,否则,当我们得到类别入口URL时,我们先把它扔进队列,等等。当我被带出排队,我爬得更深。

  接下来,在获取到收录

新闻内容的 url 后,我们应该对我们要提取的内容进行页面分析。爬虫学习者都知道,正则表达式是用来提取我们需要的内容的,但是你也应该知道,正则表达式提取的鲁棒性真的不讨人喜欢,而且写起来很困难,也很复杂(虽然应该是高效的)最高,一切都有两个方面)。所以我强烈推荐使用 CSS 选择器或 xpath 语法。它是java中与Jsoup(python中的Beatifulsoup)一起使用的神奇工具,它们的语法简单,使用方便,定位准确,健壮。而且,在查看页面中的某个元素时,右键单击可以直接获取其css路径或xpath路径。

  

  只是复制的路径一般不能直接使用。比如一条新闻的内容用ap标签括起来,如body> section.article-wrapper> article> p:nth-child(3) ,你得到的是一个绝对路径,即, 提取内容的时候准确定位到这一段,如果要获取整个新闻的内容,必须获取同级路径下所有p标签的内容,并加起来。

  

  因此,必须掌握必要的css和xpath语法,然后根据需要灵活组合。

  在爬取过程中,部分页面是异步加载的,需要点击展开剩余元素才能获取全部内容。这种情况其实很容易处理,但是当我第二次爬行时,手机搜狐又被修改了。第一次,剩余的内容真的不在当前页面中。我们需要重新发送http请求来获取剩余的内容。返回的是一个json字符串(怎么知道请求的地址?和上面解析url特征一样,只要F12先) 打开控制台,点击network,然后点击展开剩下的tab,就会向服务器发送请求,多试几次,可以找到url的特征)。但是第二次,剩余的内容已经在当前页面了,只是没有展开,

  

  异步加载页面

  以上就是一个从分析到得到我们想要的东西的过程。所以只实现了基本功能。如何构建一个健壮的爬虫?如何判断URL是否被重新丢弃?如果爬虫被阻止怎么办?

  对于健壮性,可以说即使使用CSS过滤器和xpath语法,也不能保证解析时不会出现问题。我的解决方案是在定位元素和解析内容时尽可能使用try catch语句或者if else。声明,所有可能的异常都作为异常处理。否则,就像我当时所做的那样,报告各种数组越界等异常。

  至于去重算法,我知道大神使用了强大的bloomFilter算法,即使在海量数据的情况下,依然可以高效判断字符串权重。原理是四个哈希函数的叠加。想了解的朋友可以自行网上搜索。

  可以说短时间内对同一目标网站的大量请求肯定会被服务器拦截。然后我们自然而然的想到了不断的改变IP。有许多可用的网站提供代理 IP。针对这个问题,我也写了一个miniSpider,在爬取代理IP的同时测试代理IP,因为在我们的程序中更改IP后并不是所有的代理IP地址都可用,所以确认测试可用然后保存到一个本地文件。测试IP是否可用的URL为:。

  当然,要想提高效率,多线程是必不可少的(想想一个蜘蛛和十个蜘蛛同时工作的效率差异)。多线程可以由一个线程池维护,同时启动另一个监控线程池中线程数的线程。如果线程池中的线程数小于一定数量,则重新创建多个线程。如此一来,爬虫几日几夜就几乎挂不住了。

  当然,如果你想暂停爬虫,开始爬取新闻URL而不重复,那么你可以将URL队列的数据结构序列化并存储在本地,然后每次启动时自动读取。

  最终我的爬虫爬了一个晚上一共爬了40w条新闻数据,但是在后来的检查中发现分类失衡很严重。某类新闻一共10w多条,其中一个分类的也少得可怜。数以百计。这也会对我以后的训练文本分类产生影响。原因很容易理解。相同类别的 URL 总是放在一起在队列中。如果前面的队列没有被抓取,后面的就完全没有机会了。解决办法是随机打乱队列,但我还没实现。

  

  部分数据截图

  结束语

  其实写一个好的爬虫是一个阶段性的过程,最重要的是先掌握http和html的知识。写爬虫不需要精通html的写法,但一定要懂。一开始,我不熟练,练习了很多。

  关于代码,我下次上传到Github后分享一下。

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

  2017.5.2更新

  代码地址:

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线