网页数据抓取怎么写(有没有遇到过这样的一个场景,我想大多数人第一反应就是爬虫)

优采云 发布时间: 2022-01-02 06:20

  网页数据抓取怎么写(有没有遇到过这样的一个场景,我想大多数人第一反应就是爬虫)

  不知道大家在日常的工作、学习和生活中是否遇到过这样的场景,就是需要对网站上面的一些数据进行转换(比如图片、文字或者其他一些数据格式)复制、保存到本地Excel表格、本地数据库或下载(如果是图片、音频或视频)。

  看到这样的场景,相信大多数人的第一反应就是爬。 Crawler,顾名思义就是用编写好的程序,像虫子一样在蜘蛛网上爬取我们想要的数据。

  

  根据爬虫的自动爬取能力,我经常将爬虫分为以下三个级别:

  1、手动:完全依赖手动复制粘贴;

  2、*敏*感*词*:需要为不同地方的程序手动设置相关参数,一次只能爬取一部分数据;

  3、 全自动:程序一旦运行,就知道程序的爬取完成,整个过程不需要人工干预。

  当然,第一种实际上并不是真正意义上的爬虫;第二种需要人工协助,但开发相对简单;第三种,它的爬虫过程很智能,但是写这个爬虫需要相当的知识。

  第二个和第三个,没有确定的数量是好是坏。根据不同的场合,两者都有自己的适应。比如第二种,如果要爬取的数据很简单一、,那么完全没必要写一个比较完整的程序。可以直接写一个很简单的,然后手动设置;但是如果这个程序需要爬取大范围的数据。这时候,如果需要手动设置每个关键点,那将是非常可怕和耗时的。

  

  好了,说了这么多,现在来看看这个案例。作者这几天在找PR软件的视频教程,通过搜索引擎找到了视频教程网站。

  

  这套教程分为很多章节,每一章节又分为很多小节,每个小节对应一个视频。作者的思路是提取出各个版块的名称(如:1.1 Premiere 2017下载安装)和视频地址。

  名称比较好说,表格最左边的一列是section的名称。通过查看网页的源码,可以看到源码中的table标签中有节名,但是问题的关键是如何提取table标签下的a标签中的节名,因为这是网页源代码。不能简单地通过js发送HTTP请求获取源码进行分析(因为跨域问题)。

  

  我能做什么?

  别担心,只要你的头脑不滑,解决方案总是比问题多。是的,这时候我想浏览器也有可以运行js代码的Console,最好是操作这里review元素中看到的元素。所以你可以使用下面的代码来获取所有收录section名称的a标签。

  document.querySelectorAll('.news_list table div[align="left"] a');

  

  但是这里得到的A标签收录了章节标题所在的A标签,作者只需要subsection标签。通过比较章节标题和章节标题,可以发现章节标题有固定格式的开头,而章节标题没有。这个固定格式的开头是“number.number.number”,可以用下面的正则表达式表示:

  ^\d+\.\d+(\.\d+)?

  所以可以使用正则表达式条件进行过滤,代码如下:

  var regex = /^\d+\.\d+(\.\d+)?/;

var aTags = document.querySelectorAll('.news_list table div[align="left"] a');

var list = [];

aTags.forEach(function(a) {

var text = a.innerText;

if (regex.test(text)) {

list.push({title: a.innerText});

}

});

  

  此时,我们已经提取了部分标题!接下来我们需要提取视频的地址。首先,我们点击某个部分,我们可以看到页面上有一段视频在播放:

  

  通过查看元素,可以看到有一个Video标签,标签中的src属性只是给出了视频地址。但是作者无法通过点击每个部分来查看Video标签并提取视频地址。这时笔者通过对比不同版块发现视频地址有规律:

  

  所有的视频地址只有这里的{1}不同,这里的{1}和段号有关:{1}的部分从段号变成了句号,只有标题是需要 只需提取数字并替换它。

  

  到此为止,所有的代码都可以写完整了,可以根据代码实现需要的爬取任务。

  var urlTemplate = 'http://www1.51shiping.com/pr2017/mp9/{1}.mp4';

var regex = /^\d+\.\d+(\.\d+)?/;

var aTags = document.querySelectorAll('.news_list table div[align="left"] a');

var list = [];

aTags.forEach(function(a) {

var text = a.innerText;

if (regex.test(text)) {

var no = regex.exec(text)[0].replace(/\./g, '-');

var url = urlTemplate.replace('{1}', no);

list.push({title: a.innerText, url: url});

}

});

console.log(JSON.stringify(list));

  

  可以看出这个需求并不难,所以我们不需要写一个非常完整或者强大的爬虫,只需要写十多行JS代码就可以实现功能。这样做的好处是方便快捷,但是扩展性很差。因此,在我们日常的开发和工作中,一定要懂得取舍。

  如果你碰巧遇到和我一样的问题,那么这个案例会给你一个启发。如果灵感有用,请关注和喜欢我。如果你是大神,也请在下方评论区写下你的想法。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线