基于Nodejs的爬虫框架Tai-Spider

鼎鼎大名的Scrapy是基于Python的爬虫框架,Tai-Spider就是基于Nodejs的Scrapy,下面我们就来看看这个框架有哪些能力吧。

官方提供了爬虫示例项目 tai-spider-example

安装

直接使用 npm 或者 yarn 安装即可

npm install tai-spider

或者

yarn add tai-spider

编写第一个爬虫

官方示例采用了和Scrapy一样的例子,即在spider目录下创建quotes.js,该爬虫继承了TaiSpider,其代码如下所示:

'use strict'

const { TaiSpider, ItemLoader } = require('tai-spider');

class QuotesSpider extends TaiSpider {

    constructor(options = {}) {
        super(options);
        this.name = 'quotes';
        this.debug = true;
        this.start_urls = [
            'https://quotes.toscrape.com/page/1/',
        ];
    }

    *parse(response) {
        for (let ele of response.css('div.quote')) {
            yield {
                'text': response.css('span.text', ele).text(),
            };
        }
    }
}

module.exports = QuotesSpider;

在这个例子里 QuotesSpider 作为 TaiSpider 的子类,定义并实现了一些属性和方法:

  • name:用于标识spider,它在项目中必须是唯一的,也就是说,不能为不同的spider设置相同的名称。

  • start_urls:起始urls,后续请求将从这些初始请求连续生成。

  • parse():该方法将被调用来处理每个请求下载的响应,response参数是Response类的一个实例,它提供了一些便利的方法来处理页面元素。parse方法通常用于解析响应,将抓取的数据提取为json对象、查找要跟踪的新URL,并从中创建新请求。

运行Spider

为了运行刚刚编写好的spider,你需要进入项目的顶层目录,并执行如下命令:

taispider run quotes

这个命令将运行我们刚刚编写的名为 quotes 的爬虫,它将向 quotes.toscrape.com 发送一些请求,我们可以得到类似下面的输出:

run spider: quotes
start url: https://quotes.toscrape.com/page/1/
[2021-11-06T09:31:44.570] [DEBUG] taispider - seenreq is initialized.
[2021-11-06T09:31:46.991] [DEBUG] taispider - connect to a new https://quotes.toscrape.com
[2021-11-06T09:31:48.027] [DEBUG] taispider - Http2 session https://quotes.toscrape.com connection init
[2021-11-06T09:31:48.675] [DEBUG] taispider - https://quotes.toscrape.com/page/1/ stream ends
[2021-11-06T09:31:48.676] [DEBUG] taispider - Got https://quotes.toscrape.com/page/1/ (11053 bytes)...
[2021-11-06T09:31:48.694] [DEBUG] taispider - Queue size: 0

parse 方法中你可以通过css表达式来对HTML元素进行选取,具体的css表达式规则可以参考 cheerio.

你也可以将抓取到的数据保存到文件中而不是打印到屏幕上,你只需要加上如下的命令行参数即可:

taispider run quotes -o result.jl

递归抓取页面中的链接

parse() 方法不仅用于抓取页面中的数据,还可以获取下一步抓取的链接。可以使用 follow 或者 follow_all 生成新的抓取请求,同时还允许你为这个请求指定新的回调处理函数。

在下面这个例子中,就创建了一个名为 parseAuthor 的新方法来处理新的author页面:

'use strict'

const { TaiSpider, ItemLoader } = require('tai-spider');

class QuotesSpider extends TaiSpider {

    constructor(options = {}) {
        super(options);
        this.name = 'quotes';
        this.debug = true;
        this.start_urls = [
            'https://quotes.toscrape.com/page/1/',
        ];
    }

    *parse(response) {
        for (let ele of response.css('div.quote')) {
            yield {
                'text': response.css('span.text', ele).text(),
            };
            yield* response.follow_all(response.css('span a', ele), this.parseAuthor);
        }
    }

    *parseAuthor(response) {
        const extract_with_css = (query) => {
            return _.trim(response.css(query).text());
        }

        yield {
            'name': extract_with_css('h3.author-title'),
            'birthdate': extract_with_css('.author-born-date'),
            'bio': extract_with_css('.author-description'),
        }
    }

}

module.exports = QuotesSpider;

使用model

在parse方法中除了可以直接使用json对象,也可以使用 ItemLoader 来简化数据的抽取,通过预先定义好model,你就可以简单地仅使用 load_item 方法就可以完成数据的抽取。

    *parseAuthor(response) {
        const loader = new ItemLoader(response, require('../model/author'));
        yield loader.load_item();
    }

model/author.js

const Item = require('tai-spider').Item;

module.exports = new Item({
    name: 'h3.author-title',
    birthdate: {
        value: '.author-born-date',
        type: 'date',
    },
    bio: '.author-description',
});

下载图片文件

有时我们需要下载大量的图片文件,使用 TaiSpider 框架,可以仅仅通过设置几个简单的属性就可以完成图片文件的下载。

  • IMAGES_STORE 用于指定输出路径
  • Image 对象用于指定输出图片的属性,包括 url, type, filenamebody

如果没有给出 filename 属性,框架会自动根据 url 生成MD5值来作为文件名。

'use strict'

const { TaiSpider } = require('tai-spider');
const { Image } = require('tai-spider').types;

class ImageSpider extends TaiSpider {

    constructor(options = {}) {
        super(options);
        this.name = 'image';
        this.debug = true;
        this.start_urls = [
            'https://www.mmonly.cc/gxtp/',
        ];
        this.envs['ECHO'] = false;
        this.envs['IMAGES_STORE'] = 'output';
    }

    *parse(response) {
        for (let ele of response.css('div.item')) {
            let imageEle = response.css('img', ele)[0];
            yield response.follow(imageEle.attribs['src'], this.parseImage, { filename: imageEle.attribs['alt'] + '.jpg' });
        }
    }

    *parseImage(response) {
        yield new Image({
            url: response.options.uri,
            type: 'jpg',
            filename: response.options.filename,
            body: response.body,
        });
    }
}

module.exports = ImageSpider;

执行上述爬虫,你就可以在 output 目录下得到所有下载的图片文件。

这么好的爬虫框架,赶紧开始用起来吧,Github地址在这里: Tai-Spider

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • Scrapy 框架 (本文仅用作个人记录) - Scrapy框架是用纯python实现一个为了爬去网站数据,提取结...
    wwxxee阅读 832评论 0 3
  • 1.框架架构图: 2.各文件功能 scrapy.cfg 项目的配置文件items.py 定义了Item数据结构,...
    朝畫夕拾阅读 296评论 0 0
  • 目录 参考 概述 安装 编写scrapy程序 问题总结 1. 参考 [1] docs.scrapy.org/en/...
    smallest_one阅读 731评论 0 6
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,041评论 0 4
  • 公元:2019年11月28日19时42分农历:二零一九年 十一月 初三日 戌时干支:己亥乙亥己巳甲戌当月节气:立冬...
    石放阅读 6,877评论 0 2