
1.6 小试牛刀——出版社新闻资讯爬虫
前面学习了网络请求库、文本解析库和数据存储库的使用方法,本节我们将动手爬取网页上的新闻资讯,以将学习到的知识付诸实践。我们的任务是爬取电子工业出版社官网新闻资讯栏目中的新闻资讯信息,包括新闻标题、新闻概述、封面图和发布时间。新闻资讯栏目界面如图1-33所示。

图1-33 新闻资讯栏目界面
确定需求后,我们便进入分析流程。每页有8条资讯,所有的资讯分布在46页中,这意味着爬虫程序必须像翻页一样依次访问资讯页。每页的资讯布局和对应的Elements面板如图1-34所示。

图1-34 资讯布局和对应的Elements面板
每条新闻资讯的信息包裹在li标签中,发布时间由span标签包裹,资讯标题由class属性为li_news_title的p标签包裹,资讯概述由class属性为li_news_summary的p标签包裹,封面图由img标签包裹。手动点击页码切换按钮,观察到不同页面的URL存在一定规律,页码数为1~5的URL如下:

除了第1页之外,其他页码数与URL中index后面跟着的数字的趋势相反,页码数递增则URL后缀数字递减。完成分析之后,我们便可以开始编写爬虫程序了。首先搞定单个页面的数据爬取工作,对应的代码如下:

代码的第4行使用Requests库向资讯页的第1页发出网络请求,Requests库的使用方法我们在1.4.1-1节中学习过。代码的第5行将响应正文传递给Parsel库,我们在1.4.2节使用过Parsel库。代码的第6、8、9、10、11行利用我们在1.4.2-1节学习的CSS选择器语法配合Parsel库从响应正文中提取想要的数据。最后的print()方法将提取到的资讯标题、发布时间和封面图URL打印出来,代码运行结果如下:


从打印结果中发现两个问题:
(1)有些资讯没有封面图。
(2)封面图URL不完整。
没有封面图的资讯,我们可以设定一个默认值来进行字段占位;有封面图的资讯,URL可以借助Python内置的urljoin()方法解决,对应的代码如下:

这样就能够得到完整的封面图URL。从单个页面中获取资讯信息的问题解决了,接着解决翻页爬取的问题。翻页爬取在爬虫工作中是非常普遍和常见的需求,翻页的样式、翻页的规则和触发条件有很多种不同的搭配,没有特殊技巧,见招拆招即可。这里的翻页规则刚才分析过了,页码数增加则URL中的后缀数字就降低,爬取时只需要知道最后一页的页码数或者资讯总数即可。从网站上可以看到最后一页的页码数为46,那么第2页的URL后缀数字肯定是45,通过for循环构造URL并循环爬取即可,代码逻辑如下:
(1)循环构造除第1页外的所有资讯页URL。
(2)将资讯页第1页的URL添加到URL队列中。
(3)循环URL队列,并在循环过程中爬取数据。
对应的Python代码如下(其中...表示省略部分内容):


我们在1.5节中学过如何将数据存入数据库,现在我们将按照1.5.2节介绍的方法将资讯信息存储到MongoDB数据库中。导入PyMongo库并建立连接的代码如下:

接着在获取到title、desc、pub_time和full_image后将它们存入MongoDB即可。代码片段1-9为本次爬取电子工业出版社新闻资讯的完整代码。
代码片段1-9


用可视化软件Robo3T连接MongoDB数据库并打开对应的集合,集合中的文档信息如图1-35所示。

图1-35 MongoDB中存储的文档信息
可以看到资讯信息全部存储到MongoDB数据库中了,这说明爬虫程序运行正常、数据完整,爬取电子工业出版社新闻资讯的任务完成。