【Web编程实践课第一次作业】体育新闻爬虫

僕の世界から君を無くしたら   如果我的世界没有你
意味が無いから         无论何事都尽失意义
君の世界まで僕が向かうから   我会向着你的世界奔去
待っててくれるかな       请你等着我好吗
——《君のいない夜を越えて》

跑错片场了。

2020年3月12日上午8:00~9:30,通过微信群平台,我们完成了Web编程第一次实践课;而在13日,我也完成了第一次作业的编程任务。

实验内容

此次实验的内容是,通过Node.js实现一个新闻爬虫,从3~5个新闻网站中爬取新闻信息,同时提取出标题、摘要、内容、时间、作者、来源等等信息。

要求是,必须使用Node.js实现爬虫,用Node.js实现网络后端,用HTML实现前端,且不使用任何前端框架。

实验效果

先看最终的效果如何——

前端效果:
前端效果
单关键词搜索效果:
单关键词搜索
多关键词搜索效果:
多关键词搜索

准备

首先使用npm安装cheerio和request包,方法是,在控制台输入

npm install -g cheerio
npm install -g request

但事实证明,npm给我扔了一个EINVALIDPACKAGENAME异常,百度后得知,国家有一堵伟大的墙挡住了我学习的脚步。

于是我在用户文件夹下的.npmrc文件中加入了如下几行:

proxy=null
registry=https://registry.npm.taobao.org/
disturl=https://npm.taobao.org/dist

使用了淘宝的镜像站,成功下载了cheerio和request依赖包。

分析页面

虎扑

首先在程序中敲入如下代码:

'use strict';   //使用严格模式

var http = require('http');         //http包
var myRequest = require('request'); //request包
var myCheerio = require('cheerio'); //cheerio包,用法与jQuery极其相似
var fs = require('fs');                 //fs包,用于读文件

function getNewsPage(url, callback) {
          //请求新闻导航页
    var options = {
   
        url: url, encoding: null, headers: null
    }
    myRequest(options, callback);
}

function request(url, callback) {
              //请求某一新闻帖页面
    var options = {
   
        url: url,
        encoding: null,
        headers: null
    }
    myRequest(options, callback);
}

//标题、内容、编者、来源、时间以及新闻地址
var Titles = new Array();
var Contexts = new Array();
var Editor = new Array();
var ComeFrom = new Array();
var ComeURLs = new Array();
var DateTime = new Array();
var URLs = new Array();

接着,我们进入虎扑的四个新闻网站:

https://voice.hupu.com/soccer
https://voice.hupu.com/nba
https://voice.hupu.com/china
https://voice.hupu.com/cba

按F12审查元素,观察他们的前端代码:
虎扑新闻导航页
我们得到一个结论:进入这些新闻页面的链接,都在每个h4标签中的a子标签的href属性之中。
接下来,我们点开一个页面进入,并查看源码:
虎扑新闻帖页面
可以看到,新闻的标题正好是网页的标题title的内容,正文则是div[class=“artical-main-content”]标签下的内容,编者、来源、时间等分别来自于span[id=“editor_baidu”]、span[class=“comeFrom”]的a子标签、span[id=“pubtime_baidu”]。

顺便吐槽一句,为什么命名为baidu呢,和百度公司有关系吗?

那么虎扑新闻网的爬虫也就写好了:

var hupuSpider = {
   
    NewsURLs : [
        "https://voice.hupu.com/soccer",
        "https://voice.hupu.com/nba",
        "https://voice.hupu.com/china",
        "https://voice.hupu.com/cba"
    ],                                          //虎扑的几个新闻网页
    GetURL: function (err, res, body) {
            //从新闻总页获取统一资源定位器,并爬取信息
        var BuildDataset = function (err, res, body) {
   
            if (err || res.statusCode != 200) {
        //失败
                Titles.push(`新闻抓取失败-${
     err}`);
                Contexts.push('暂无内容');
                Editor.push('暂无编者');
                ComeFrom.push('暂无来源');
                ComeURLs.push('');
                DateTime.push('暂无时间')
            } else {
   
                let html = body;                    //网页源码,送入cheerio解析
                let $ = myCheerio.load(html, {
    decodeEntities: false });
                //console.log($.html());            //Debug代码,输出网页源码

                URLs.push(res.request.uri.href);    //将解析的信息塞进数组
                Titles.push($('title').text());
                Contexts.push($('div[class="artical-main-content"]').text());
                Editor.push($('span[id="editor_baidu"]').text());
                ComeFrom.push($('span[class="comeFrom"]').children("a").text());
                ComeURLs.push($('span[class="comeFrom"]').children("a").attr("href"));
                DateTime.push($('span[id="pubtime_baidu"]').text());
            }
        };

        if (err || res.statusCode != 200) {
        //err不为null,说明出现了异常
            console.log(`新闻抓取失败-${
     err}`);
        } else {
   
            let html = body;                    //网页源码,送入cheerio解析
            let $ = myCheerio.load(html, {
    decodeEntities: false });
                                                //找到第cnt个<h4>标签中<a>的href属性
            let cnt = 0;                        //新闻子页面的计数器
            let h4Arr = $("h4").eq(cnt);
            let str = h4Arr.children("a").attr("href");
            while (str) {
                          //如果找得到,那么输出并继续寻找下一个
                console.log(str);
                request(str, BuildDataset);
                ++cnt;
                h4Arr = $("h4").eq(cnt);
                str = h4Arr.children("a").attr("href");
            }
        }
    }
};
球天下

由于期望获取到的信息更加多元化 (其实是不满虎扑爬取难度过低) ,3月23日,我为爬虫添加了球天下这一新闻获取渠道。

比起虎扑,球天下的爬取难度略微高一些。

球天下主要有两个新闻网页:

https://www.qtx.com/
https://www.qtx.com/others

这两个网页虽然看起来并不一样,但前端代码还是有几分相似的。

首先,观察发现,所有新闻内容都在div[class=“baseNewsList”]之中:
球天下主页面中的新闻
球天下others页面中的新闻
其次,所有的链接都在h3、h4、div[class=“media-body”]、a这四种标签之中。所以,只要用cheerio定位这些标签就可以。

接下来就是每个新闻网页中内容的提取了,随便点开一个网页:
费莱尼确诊新冠的新闻页面
我们发现,其网页标题依然是新闻标题,正文位于div[class=“artContent”]标签中。编者反而位于右侧,是球天下的注册用户,其用户名位于div[class=“bzhead”]标签下的p子标签中。来源和时间都在div[class=“mes”]标签中,需要根据空格来分离开。

那么球天下的爬虫也可以写好了:

var qtxSpider = {
   
    NewsURLs: [
        "https://www.qtx.com/others",
        "https://www.qtx.com/"
    ],                                          //球天下新闻网页
    GetURL : function (err, res, body) {
           //从新闻总页获取统一资源定位器,并爬取信息
        var BuildDataset = function (err, res, body) {
   
            if (err || res.statusCode != 200) {
        //失败
                Titles.push(`新闻抓取失败-${
     err
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值