文享日志

基于WebSplider的在线新闻模块开发

爬虫

发表于2018年06月14日23:18:28

更新于2018年07月05日13:27:14

0条评论 575次阅读

目标:

      爬取澎湃新闻网站的新闻,作为我们新闻站点的数据源,构建我们的新闻站点。

      我们的新闻站点有两层:首页和文章详情页。首页是文章的链接与简介,文章详情页是文章内容。


获取数据源:

      数据源可以利用我们的WebSplider在线爬虫系统,获得数据接口。我们的新闻站点有两层,所以需要两个数据接口,分别用来构造首页内容与文章详情页内容。


首先进行我们新闻站点首页数据的抓取:

我们要抓取的部分是澎湃新闻首页每个新闻卡片的文章标题,文章简介与文章链接。

不需要点击网页中任何一个链接进入下一层,所以爬取深度为 1

澎湃新闻


设置爬虫目标地址:https://www.thepaper.cn/


然后我们观察网页结构:

澎湃新闻


72DD38C19DB895F201EF4B5AD0EBD78A.png

第二个图中,第一个框即为新闻链接与新闻文章标题,第二个框是新闻简介。


通过构造合适的选择器,定位到这两类元素上:

      首先定位这里的a元素,可以看到,元素有id属性,id值具有唯一性,所以这里我们并不能使用id属性来获取。因为id属性只能获取到这一个a标签元素,而我们要获得的是每一个类名为news_li元素下的h2元素下的a元素。。所以这里只能根据标签选择器来选择到这类元素。观察a标签的父节点为h2,h2的父节点类名为news_li。


所以可以构造如下选择器:

$(".news_li").children('h2').children('a')


由此可获得a标签的链接

$(".news_li").children('h2').children('a').attr('href')


获得a标签的文字

$(".news_li").children('h2').children('a').text()


定位p元素与定位a元素类似,可构造如下选择器:

$(".news_li").children('p')


由此获得p标签中的文字

$(".news_li").children('p').text()


此时,我们爬虫配置中,最难的部分就基本搞定了。。

现在要做的是,将上面获得的几个选择器中公共的部分(  $(".news_li")  )提取出来,填写到WebSplider选择器中。

将剩下的部分,构造在输出格式中。

输出格式构造如下:

{
"title":"$element.children('h2').children('a').text()",
"href":"'https://www.thepaper.cn/'+$element.children('h2').children('a').attr('href')",
"brief":"$element.children('p').text()"
}

注:输出格式必须写为JSON数据格式。


可以看到:

1、这里有个$element,这个东西就指的是我们的标签选择器中填写的内容(   $(".news_li")   )。

2、输出格式中,value值的部分支持简单的字符串拼接(看图片a元素链接,并不是完整的链接,所以要拼接)。

3、其实到这里也可以看出来,WebSplider选择器其实是在给一张网页定一个基地址,以使得输出格式所有键值可以由基地址定位到我们需要的元素。所以,选择器也可以填写诸如这样的东西:$('html'),$('body') 。。


完整的首页配置如下:

WebSplider


进行文章内容的爬取:

         首先想一下我们看新闻的过程,打开澎湃首页,看到感兴趣的文章标题,点进去看文章。爬虫爬的过程与人一样,首先要得到首页文章标题的所有url,再对所有url进行爬取。通过适合的选择器,再找到文章内容。通过这个过程,可以想到进行一级爬取、二级爬取、三级爬取所需的时间会越来越长,为了不影响用户体验,所以我们在后台编写代码需要合适的数据接口请求策略,比如:请求一次数据接口后,将结果缓存到本地,定时器启动,1小时后再请求数据接口,再更新本地缓存。。


我们这里将爬取深度设置为2

目标网址还是https://www.thepaper.cn/


一级选择器中填写首页获得的新闻的链接,以便二级选择器请求一级选择器选到的url。

一级选择器填写示例:

$(".news_li").children('h2').children('a')


二级选择器填写使用我们上面讲到的策略,填写即可。

二级选择器填写示例:

$(".newscontent")


输入格式填写:

{
"title":"$element.children('.news_title').text()",
"content":"$element.children('.news_txt').text()"
}

这里的$element指的是$(".newscontent")


完整文章详情页配置如下:

WebSplider



预览爬取结果后,觉得满意,点击右下角“生成数据接口”(需注册登录),即可获得数据接口。



后台开发

          数据接口准备好后,进行后台开发。

          后台语言使用nodejs,使用express框架与ejs模板,使用axios http请求库。


      完整的代码就不在这里展示了,感兴趣的可以点击这里查看完整demo。网页打不开的可以看看这篇文章:ec2搭建ss服务器


核心代码如下:

处理首页请求

router.get('/', function(req, res, next) {
    axios.get("http://splider.docmobile.cn/interface?name=luckyhh&cid=1528858061500").then(ires=>{
       res.render('index', { title: '每日要闻' , content :ires.data});
    }).catch(err=>{
       console.log(err);
    });
});


index模板

。。。。。其他HTML元素。。。。。

<h1><%= title %>h1>

<%

       var basehref = 'localhost:3000';

       content.forEach(function(con,idx){

%>

<h2><a href="<%=basehref+'/news/'+idx%>" target="_blank"><%=con.title%>a>h2>

<p><%=con.brief%>p>

<%

       })

%>

。。。。。其他HTML元素。。。。。



处理文章页请求

router.get('/news/:num',function(req,res,next){
   axios.get("http://splider.docmobile.cn/interface?name=luckyhh&cid=1528859571224").then(ires=>{
       res.render('news',{title:'文章',content:ires.data,num:req.params.num});
   }).catch(err=>{
       console.log(err);
   });
})


news模板

。。。。。其他HTML元素。。。。。

<h1><%= title %>h1>

<%

     for(var i = 0 ; i < content.length ; i++){

        if(num == i){

%>

<h2><%=content[i][0].title%>h2>

<p>

    <%=content[i][0].content%>

p>

<%

    break;

   }

}

%>

。。。。。其他HTML元素。。。。。



Demo演示地址:

https://www.docmobile.cn/hotnews


👍 0  👎 0
共有0条评论

发表新评论

提交

广告展示

腾讯云推广 阿里云推广