V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
j1wu
V2EX  ›  分享创造

让命令行生活更丰富些~ cli-scraper

  •  1
     
  •   j1wu ·
    j1wu · 2017-11-17 13:01:45 +08:00 · 2704 次点击
    这是一个创建于 2564 天前的主题,其中的信息可能已经有所发展或是发生改变。

    cli-scraper 的外表下其实是一个基于 Node 的网页爬虫库,开发初衷是希望能帮助大家更方便的开发自己的爬虫,以便在命令行中浏览静态网页内容。如果你和我一样,生活在命令行世界中,那它给了你又一个留下的理由。😂

    p.s. 库名比较怪,因为它并非可以爬 命令行中的内容,或许 scraper-for-cli 会更好一些?命名不易啊!

    全局安装后,要让 cli-scraper 开始工作,仅需如下三步:

    1. 运行 $ clis init hello.js 这条命令,新建一个新的配置文件。
    2. 通过编写 CSS 选择条件,告诉 cli-scraper 如何定位到你希望从网页中提取的内容。
    3. 最后,运行 $ clis process hello.js

    话不多说,上🌰

    范例 - 访问 https://bing.com 并提取 logo 文本:

    运行 init 命令生成配置文件 $ clis init bing.js

    // 如下是完成后的配置文件,复制粘贴到你本地的 bing.js ,试试吧。
    module.exports = {
      url: 'https://www.bing.com/',     // 目标地址
      process: function ({ $ }) {
        return $('.hp_sw_logo').text()  // 选中目标元素,并提取其中文本
      },
      finally: function (res) {
        console.log(res + 'go :)')      // 结果任你处置
      }
    }
    

    运行 process 命令开工 $ clis process bing.js

    上面就是让 cli-scraper 工作的最小配置,你本地生成的默认配置文件中的属性更多,我会在随后的篇幅中对其逐一说明,在此之前,让我们再举一个 🌰。

    先假想一个场景,你想在命令行中查看最常去新闻网站的更新,不仅是新闻列表,还想知道每篇文章中的一些内容(譬如发布时间),你最终希望在命令行中看到的输出是 新闻标题 [at] 发表时间

    范例 - 快速查看新闻网站更新:

    运行 init 命令生成配置文件 $ clis init news.js

    // // 如下是完成后的配置文件,复制粘贴到你本地的 news.js ,试试吧。
    module.exports = {
      url: 'http://www.news.cn/world/index.htm',
      requestOptions: {
        timeout: 10000                     // 如果 10 秒还未成功则放弃
      },
      randomUserAgent: true,               // 在访问时随机伪装 user-agent
      printRequestUrl: true,
      randomWait: 5,                       // 每次请求随机间隔 1 到 5 秒
      process: function ({ $ }) {
        return $('.firstPart ul.newList01 > li > a').map((i, el) => {
          return {
            articleUrl: $(el).prop('href'),
            title: $(el).text()
          }
        })
      },
      next: {
        key: 'articleUrl',                 // 新闻列表结果中的新闻文档链接健
        process: function ({ $, prevRes }) {
          return Object.assign(prevRes, {  // 合并列表和对应的文章结果
            date: $('.h-news > .h-info > .h-time').text()
          })
        }
      },
      finally: function (res) {
        for (let item of res) {
          if (item.date) {
            console.log(`${item.title} [at] ${item.date}`)
          }
        }
      },
      catch: function (err) {
        console.log(err)                   // 如果遇到异常,打印出来
      }
    }
    

    运行 process 命令开工 $ clis process news.js

    配置详解请参见 Github README

    为了做个好爬虫(请尊重 Robots.txt ),在默认配置中加入了些限制,譬如:

    promiseLimit: Number (默认: 3) 试想你在第一个提取函数中提取到了 10 个下一层链接,由 next 中的提取函数接手处理,第二层的提取函数将对这 10 个链接进行并行处理,而这个设置对并发数进行了限制。

    randomWait: Number (默认: 5) 每次请求随机间隔 1 到 5 秒。

    urls: 对传入的 url 数组进行串行处理。

    在开发中,没有选择使用 async / await,而用的是原生的 Promise,因为感觉这样写出来的 data pipeline 看起来更加直观,Happy coding :)

    4 条回复    2017-11-18 17:54:34 +08:00
    tedd
        1
    tedd  
       2017-11-17 15:24:28 +08:00
    这个可以有! Orz
    Charkey
        2
    Charkey  
       2017-11-17 22:13:53 +08:00
    厉害啦,膜拜一下
    gap
        3
    gap  
       2017-11-18 09:35:19 +08:00
    支持 ajax 动态加载的内容吗?
    j1wu
        4
    j1wu  
    OP
       2017-11-18 17:54:34 +08:00 via iPhone
    @gap 计划在下个版本中加入。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2751 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:12 · PVG 18:12 · LAX 02:12 · JFK 05:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.