从零开始的爬虫项目(一)

引言

本人是只有c语言基础的编程本科小白,进入大学之前从来没有接触过编程知识。ddl是生产原动力,不得不开始从零学习如何编写新闻爬虫,旨在发现问题解决问题,总结心得,记录生活,而非提供专业方面的建设性意见。

由于从未学过JavaScript语言,空手做起来难于登天。课程老师给我们这样的项目的时候也考虑到了这一问题,会同步在课程中教授nodejs语法,也会展示部分爬虫样例,对我来说如何参照代码,掌握每一步的意图并仿照进行别的网站的爬虫项目才是这个作业于我有意义的的地方。

实验要求

  1. 选取3-5个代表性新闻网站建立爬虫
  2. 针对不同网站的新闻页面进行分析,爬取出编码、标题、作者、时间、关键词等结构化信息
  3. 存储到数据库中
  4. 建立网站供对爬取内容进行分项全文搜索,给出所查关键词的事件热度分析

第一次实践

要想爬取编码、作者等结构化信息,学会分析不同网站的新闻页面是关键。我把首个爬取目标设为新浪新闻网。

使用Chrome浏览器打开“新浪新闻网”(https://new.sina.com.cn) , 随便点开首页的一则新闻,按F12 点击“Elements"即可查看该新闻页面的html文件,点击左上角箭头,移动光标至新闻页面各分区还可看到html文件中与之相对应的语句。

当然,更一般的,新闻页面右键”查看源代码“即可在新建页面中看到完整的html文件,我还是更倾向于这种的,比较直观清晰。
在这里插入图片描述
接下来就是分析新闻页面的html文件,找到关键信息所处的位置。

在这里插入图片描述

仔细阅读的话不难发现,在新浪新闻网的一般新闻网页中,关键词放在名为“keywords”的meta标签中,而标题放在title标签中。

在这里插入图片描述
又如,概要放在meta property=“og:description”(meta property=og表示同意了网页内容可以被其他社会化网站引用)标签中。

这种模式适用于新浪新闻网的大部分新闻页面。确定了一个网站各关键信息所处位置后,方能定义其读取方法:

1 var title_format = "$('title').text()";
2 var keywords_format = "$('meta[name=\"keywords\"]').eq(0).attr(\"content\")";
3 var desc_format = "$('meta[property=\"og:description\"]').eq(0).attr(\"content\")";
4 <meta id=xxxxxxx>    对应    "$('#xxxxxxx')."
5 <meta class=xxx>     对应     "$('.xxx')."

这里给出涉及到的方法的定义和用法供查阅:

而这些都只是对于指定页面内相关元素的爬取,想要一次性爬取大量新闻页面就需要在种子页面上爬取全部的页面链接并抽出其中符合新闻链接规则的链接。
随便以一个新闻链接(https://news.sina.com.cn/c/2020-04-23/doc-iircuyvh9369753.shtml)为例。

可以看出一般规则为 “http://news.sina.com.cn/” + c(//任意字母)/ + xxxx-xx-xx/ + doc-aaaaaaaaaaaa.shtml

为此我们只需查找不同部分 c(//任意字母)/ + xxxx-xx-xx/ + doc-aaaaaaaaaaaa ,也就是 任意字母/xxxx-xx-xx/doc-字母数字串.shtml 即可。接下来需要使用JavaScript的正则表达式,根据规则,表达式应为

var url_reg = /(\w{1,2})\/(\d{4})-(\d{2})-(\d{2})\/doc-(\w+).shtml/;

将获得的大量不同格式的链接稍加编辑统一为以http://开头的链接就能用于后续操作了。

后续就是创建拥有多个属性的一个对象,并将结构化信息赋值给该对象对应的不同属性,并将该对象通过"stringify"(*相关用法
*)的方法转换成JSON字符串并以"writeFileSync"(相关用法
)方法写入一个JSON文件并保存。

遇到的问题

网站通信协议不统一

在种子页面获取符合正则表达式的有效链接后需要对其格式进行统一,但新浪新闻网页面包含的链接中混杂着支持HTTPS协议以及HTTP协议的不同链接,

if (href.toLowerCase().indexOf('http://') >= 0||
href.toLowerCase().indexOf('https://') >= 0) myURL = href;

因而两种情况均需要考虑,否则就会出现错误的链接补足:

在这里插入图片描述

新浪网站根据不同分区还有不共用一套关键信息存放规则的子网站

在这里插入图片描述
当我在运行程序时发现我创建的对象某些属性的值为undefined,因而在用replace方法进行部分内容替换时读到undefined会终止进程并报错“Cannot read property ‘replace’ of undefined ”。我顺着读取成功返回的链接找到原网址,并查看源代码,发现主网站与子网站在某些关键信息处存在差异,以发布日期为例:

 <span class="date">2020042309:33</span> 
 //此网站地址为//mil.news.sina.com.cn/china/2020-04-23/doc-iirczymi7859278.shtml
 //其位于新浪子网站“新浪军事网”
<meta property="article:published_time" 
content="2020-04-23T12:36:38+08:00" />
//网址为//news.sina.com.cn/c/2020-04-23/doc-iircuyvh9369753.shtml
//位于新浪主网站

而这并非全部,新浪有着各种以 “mil” ,"finance"等为前缀的子网站,一一通过条件判断枚举过于麻烦,且对我这种小白也不友好,因而我决定在种子页面抽有效链接的过程中添加限制条件,达到只抽取主网站新闻链接的目的,这就需要创建一个满足抽取在“news.sina.com.cn”前没有“finance.” 及 “mil.”等前缀的正则表达式。可以说正难则反,我只需要在利用之前的正则表达式筛选出有效链接的基础上,保留不符合“.news.sina.com.cn”形式的链接就好了:

1 var url_exreg = /[.]news.sina.com/;
//先写出不符合条件的链接满足的正则表达式
2 if (url_exreg.test(myURL)) return;
//再在抽取链接的循环中添加该判断条件,若符合则跳过并进行下一个循环

如此一来就用一种极不完美的方式解决了新浪子网站引发的程序报错,虽然这样一来部分新闻就无法爬取了,但是对于一个新人来说能爬到新闻就不错了!
在这里插入图片描述

小结

一天的时间里我尝试了如何分析新闻页面的html文件,并基本学会了如何写不同格式的JS正则表达式。虽然遇到了不少问题,报了一堆错,但通过百度对各种JS方法的用法有了一定的了解,并在此基础上分析出问题源头,成功爬取到了不少新闻内容,可以说是对我付出的时间的最好回报。
之前总是静不下心来,怕难,怕碰壁,对于未知总是抱有畏惧的态度。而这一天的时间里我在读写代码的过程中也学到了很多之前被灌输但是不常用过一会就会忘的语法知识,也算是给予了我一点信心吧。虽然我比不上那些爬了很多网站,精通不少JS方法的人,但是人只要和过去的自己比就好了,做到不悔即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值