成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從零開始開發(fā)一個Node交互式命令行應(yīng)用

Harriet666 / 1360人閱讀

摘要:導(dǎo)言對于大多數(shù)前端開發(fā)者而言,談到命令行工具,大家肯定都用過。但是談到開發(fā)命令行工具,估計就沒幾人有了解了。如何優(yōu)化這個圖片爬蟲工具目前還有點(diǎn)啊,我們的目標(biāo)是要開發(fā)一個交互式的命令行應(yīng)用,肯定不能止于此。

導(dǎo)言:對于大多數(shù)前端開發(fā)者而言,談到命令行工具,大家肯定都用過。但是談到開發(fā)命令行工具,估計就沒幾人有了解了。本文旨在用最短的時間內(nèi),幫您開發(fā)一個實(shí)用(斜眼笑)的圖片爬蟲命令行應(yīng)用。

想追求更好的閱讀體驗(yàn),請移步拓跋的前端客棧。同時把項(xiàng)目地址放在顯眼的位置

Puppeteer 簡介 什么是 Puppeteer?

Puppeteer 是 Google Chrome 團(tuán)隊(duì)官方的無界面(Headless)Chrome 工具。Chrome 作為瀏覽器市場的領(lǐng)頭羊,Chrome Headless? 將成為 web 應(yīng)用 ? 自動化測試 ? 的行業(yè)標(biāo)桿。所以我們很有必要來了解一下它。

Puppeteer 可以做什么?

Puppeteer 可以做的事情有很多,包括但不限于:

利用網(wǎng)頁生成 PDF、圖片

可以從網(wǎng)站抓取內(nèi)容

自動化表單提交、UI 測試、鍵盤輸入等

幫你創(chuàng)建一個最新的自動化測試環(huán)境(chrome),可以直接在此運(yùn)行測試用例

捕獲站點(diǎn)的時間線,以便追蹤你的網(wǎng)站,幫助分析網(wǎng)站性能問題

Puppeteer 有什么優(yōu)勢?

相對于真實(shí)瀏覽器而言,少了加載 css,js 以及渲染頁面的工作。無頭瀏覽器要比真實(shí)瀏覽器快的多。

可以在無界面的服務(wù)器或 CI 上運(yùn)行,減少了外界的干擾,更穩(wěn)定。

在一臺機(jī)器上可以模擬運(yùn)行多個無頭瀏覽器,方便進(jìn)行并發(fā)運(yùn)行。

如何安裝 Puppeteer?

安裝 ?Puppeteer? 很簡單,如下:
npm i --save puppeteer
or
yarn add puppeteer

需要注意的是,由于用到了 ES7 的 ?async/await? 語法 ,node? 版本最好是 v7.6.0 或以上。

如何使用 Puppeteer?

由于本文不是專門講 Puppeteer 的文章,故這部分暫且略過,大家可以去看下面的鏈接學(xué)習(xí)。

Puppeteer Github

Puppeteer Api Doc

Puppeteer 中文 Api Doc

說了這么多,Puppeteer 與我們要開發(fā)的命令行應(yīng)用有什么關(guān)系呢?我們準(zhǔn)備制作一個抓圖命令行工具,不使用傳統(tǒng)的請求式爬蟲,我們使用 Puppeteer 這種無頭瀏覽器,從 DOM 里抓圖,這樣能有效規(guī)避部分爬蟲防御手段。

Puppeteer 簡單應(yīng)用 case 1. 屏幕截圖

直接上代碼,很好理解:

const puppeteer = require("puppeteer");

const getScreenShot = async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto("https://baidu.com");
  await page.screenshot({ path: "baidu.png" });

  await browser.close();
};

getScreenShot();

這段代碼的意思就是以 headless(無頭)模式打開瀏覽器,然后打開一個新標(biāo)簽頁,跳轉(zhuǎn)到百度網(wǎng)址, 并且進(jìn)行屏幕截圖,保存為 baidu.png 為名的圖片,最后關(guān)閉瀏覽器。

執(zhí)行結(jié)果如下。

case 2. 抓取網(wǎng)站信息

接下來學(xué)習(xí)如何用 Puppeteer 抓取網(wǎng)站信息了。

這次我們來抓取 jd 書單信息。

// book info spider
const puppeteer = require("puppeteer");
const fs = require("fs");

const spider = async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto("https://search.jd.com/Search?keyword=javascript");

  const result = await page.evaluate(() => {
    let elements = document.querySelectorAll(".gl-item");

    const data = [...elements].map(i => {
      return {
        name: i.querySelector(".p-name em").innerText,
        description: i.querySelector(".p-name i").innerText,
        price: i.querySelector(".p-price").innerText,
        shop: i.querySelector(".p-shopnum").innerText,
        url: i.querySelector(".p-img a").href
      };
    });
    return data; // 返回數(shù)據(jù)
  });

  browser.close();
  return result;
};

spider().then(value => {
  fs.writeFile(`${__dirname}/javascript.json`, JSON.stringify(value), err => {
    if (err) {
      throw err;
    }
    console.log("file saved!");
  });
  console.log(value); // Success!
});

我們做的就是跳轉(zhuǎn)到關(guān)鍵字是 javascript 的頁面,然后對頁面的 dom 結(jié)構(gòu)進(jìn)行分析,找到圖書列表所對應(yīng)的書名、描述、價格、出版社、網(wǎng)頁鏈接信息,然后把數(shù)據(jù)寫入到 javascript.json 文件里去,方便我們保存瀏覽。

邏輯很簡單。這已經(jīng)是一個爬蟲的雛形了,最后得到如下圖所示的 json 文件,非常給力。

case 3. 圖片爬蟲

圖片爬蟲,這就是我們要做的命令行應(yīng)用的主題了。

一個最基本的思路是這樣的:

打開瀏覽器 —> 跳轉(zhuǎn)到百度圖片 —> 獲取 input 框的焦點(diǎn) —> 輸入 keywords —> 點(diǎn)擊搜索按鈕 —> 跳轉(zhuǎn)至結(jié)果列表頁 —> 下拉到底部 —> 操作 dom,獲取所有圖片的 src 備用 —> 根據(jù) src 將對應(yīng)圖片保存到本地 —> 關(guān)閉瀏覽器

代碼實(shí)現(xiàn)之:

首先是瀏覽器操作部分

const browser = await puppeteer.launch(); // 打開瀏覽器
const page = await browser.newPage(); // 打開新tab頁
await page.goto("https://image.baidu.com"); // 跳轉(zhuǎn)到百度圖片
console.log("go to https://image.baidu.com"); // 獲取input框的焦點(diǎn)

await page.focus("#kw"); // 把焦點(diǎn)定位到搜索input框
await page.keyboard.sendCharacter("貓咪"); // 輸入關(guān)鍵字
await page.click(".s_search"); // 點(diǎn)擊搜索按鈕
console.log("go to search list"); // 提示跳轉(zhuǎn)到搜索列表頁

然后是圖片處理部分

page.on("load", async () => {
  await autoScroll(page); // 向下滾動加載圖片
  console.log("page loading done, start fetch...");
  const srcs = await page.evaluate(() => {
    const images = document.querySelectorAll("img.main_img");
    return Array.prototype.map.call(images, img => img.src);
  }); // 獲取所有img的src
  console.log(`get ${srcs.length} images, start download`);
  for (let i = 0; i < srcs.length; i++) {
    await convert2Img(srcs[i], target);
    console.log(`finished ${i + 1}/${srcs.length} images`);
  } // 保存圖片
  console.log(`job finished!`);
  await browser.close();
});

因?yàn)榘俣葓D片是往下滾動就可以繼續(xù)懶加載。因此,我們想要加載更多圖片,可以先往下滾動一會兒。然后通過分析 dom 結(jié)構(gòu)來獲取列表里所有圖片的 src,最后進(jìn)行下載。

執(zhí)行以下,就能得到一系列貓咪的圖片:

圖片下載的地方只寫了主函數(shù),更詳細(xì)的代碼可以去參見github.

至此,我們用 Node 和 Puppeteer 開發(fā)出了一個最基本的圖片爬蟲工具。

如何優(yōu)化?

這個圖片爬蟲工具目前還有點(diǎn) low 啊,我們的目標(biāo)是要開發(fā)一個交互式的命令行應(yīng)用,肯定不能止于此。有哪些可以進(jìn)一步優(yōu)化的點(diǎn)呢?經(jīng)過簡單的思考,我列了一下:

下載圖片的內(nèi)容可以自定義

可以支持用戶選擇圖片下載張數(shù)

支持命令行傳參

支持命令行交互

交互界面美觀

支持雙擊直接運(yùn)行

支持全局命令行調(diào)用

使用 commander.js 支持命令行傳參

Commander 是一款重量輕,表現(xiàn)力和強(qiáng)大的命令行框架。提供了用戶命令行輸入和參數(shù)解析強(qiáng)大功能。

const program = require("commander");

program
  .version("0.0.1")
  .description("a test cli program")
  .option("-n, --name ", "your name", "zhl")
  .option("-a, --age ", "your age", "22")
  .option("-e, --enjoy [enjoy]")
  .action(option => {
    console.log("name: ", option.name);
    console.log("age: ", option.age);
    console.log("enjoy: ", option.enjoy);
  });

program.parse(process.argv);

Commander十分容易上手,上面這一段代碼僅用了寥寥數(shù)行,就定義了一個命令行的輸入與輸出。其中:

version 定義版本號

description 定義描述信息

option 定義輸入選項(xiàng),傳3個參數(shù),如option("-n, --name ", "your name", "GK"),第一項(xiàng)是傳參的值,-n是簡寫形式,--name是全稱形式, 表示輸入的參數(shù),<>是必填項(xiàng),如果是[],則是選填項(xiàng)。第二項(xiàng)“your name"是求助help時的提示信息,告訴用戶應(yīng)該輸入的內(nèi)容,最后一項(xiàng)"GK"是默認(rèn)值。

action 定義執(zhí)行的操作,是一個回調(diào)函數(shù),入?yún)⑹乔拔妮斎氲膐ption選項(xiàng),如果沒有輸入option,則使用定義的默認(rèn)值。

要查詢更詳細(xì)的api,請參考Commander Api文檔。

執(zhí)行一下上述腳本,可以得到:

這樣命令行就可以做到簡單的交互效果了。但是有沒有覺得不夠好看呢,別急,繼續(xù)往下看。

使用inquirer制作可交互命令行應(yīng)用

inquirer可以為Node制作可嵌入式的美觀的命令行界面。

可以提供問答式的命令輸入:

可以提供多種形式的選擇界面:


可以對輸入信息進(jìn)行校驗(yàn):

最后可以對輸入信息進(jìn)行處理:

上面的例子是inquirer的官方例子,可以參考pizza.js

inquirer的文檔可以查看inquirer documents

有了inquirer,我們就可以制作更為精美的交互式命令行工具了。

使用 chalk.js來讓交互界面更美觀

chalk的語法非常簡單:

const chalk = require("chalk");
const log = console.log;

// Combine styled and normal strings
log(chalk.blue("Hello") + " World" + chalk.red("!"));
// Compose multiple styles using the chainable API
log(chalk.blue.bgRed.bold("Hello world!"));
// Pass in multiple arguments
log(chalk.blue("Hello", "World!", "Foo", "bar", "biz", "baz"));
// Nest styles
log(chalk.red("Hello", chalk.underline.bgBlue("world") + "!"));
// Nest styles of the same type even (color, underline, background)
log(chalk.green(
??"I am a green line " +
??chalk.blue.underline.bold("with a blue substring") +
??" that becomes green again!"
));

可以輸出如下信息,一看便懂:

再讓我們做點(diǎn)有意思的事情...

想必有人看到過下面知乎的控制臺效果,既然要做點(diǎn)有意思的事情,今天我們不妨也把這種效果加到命令行程序里面,提升一下逼格。

首先我們準(zhǔn)備一副ASCII碼用來打印,各位可以自行搜索text轉(zhuǎn)ASCII,網(wǎng)上的轉(zhuǎn)化方案不要太多。我們準(zhǔn)備制作的命令行image spider就制作一個IMG SPD的ASCII碼字符串吧~

經(jīng)過挑選,效果如圖:

這種復(fù)雜的字符串怎么打印出來呢?直接保存為string一定是不行的,格式會亂的一塌糊涂。

想要能完整的打印出格式來,有一個取巧的方法,以注釋的形式打印出來。什么能保存注釋呢?~~ function。

所以事情就簡單到了打印一個function。但是直接打印函數(shù)還是不行的,這時候就用到了可以懟天懟地的toString()方法,我們只需要把注釋中間的部分用正則匹配出來就行了,easy~

最后看一看效果,鐺鐺鐺鐺~

支持雙擊運(yùn)行

這里使用一種叫做Shebang的技術(shù)。

Shebang(也稱為?Hashbang?)是一個由#和!構(gòu)成的字符序列?#!?,其出現(xiàn)在文本文件的第一行的前兩個字符。 在文件中存在 Shebang 的情況下,類 Unix 操作系統(tǒng)的程序加載器會分析 Shebang 后的內(nèi)容,將這些內(nèi)容作為解釋器指令,并調(diào)用該指令,并將載有 Shebang 的文件路徑作為該解釋器的參數(shù)。

node下我們使用#! /usr/bin/env node即可

這時候我們便可以取消文件的擴(kuò)展名.js了。

加入環(huán)境變量,支持全局調(diào)用

package.json里面配置

"bin": {
  "img-spd": "app"
},

執(zhí)行npm link,它將會把img-spd這個字段復(fù)制到npm的全局模塊安裝文件夾node_modules內(nèi),并創(chuàng)建符號鏈接(symbolic link,軟鏈接),也就是將 app 的路徑加入環(huán)境變量 PATH。

這時,在任意目錄下,直接命令行輸入img-spd即可運(yùn)行此命令行

尾聲

至此,要改進(jìn)的地方已經(jīng)全部修改完畢,快來看看我們的成品吧~

看著一整個文件夾的gakki,感覺滿滿的幸福要溢出來了

最后用動圖來展示一下:

附錄 項(xiàng)目地址

項(xiàng)目地址

Install
npm install -g img-spd
Usage
img-spd

or

Usage: img-spd [options]

img-spd is a spider get images from image.baidu.com

Options:
  -v --version               output the version number
  -k, --key [key]            input the image keywords to download
  -i, --interval [interval]  input the operation interval(ms,default 200)
  -n, --number [number]      input the operation interval(ms,default 200)
  -m, --headless [headless]  choose whether the program is running in headless mode
  -h, --help                 output usage information

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/102380.html

相關(guān)文章

  • 從零開始打造個人專屬命令工具集——yargs完全指南

    摘要:自阮大神的文章發(fā)布以來,有了一些改動,添加有很多有用的功能,特別是這個功能,對打造命令行工具集合非常有用,所以寫一個新版本的教程還是有必要的。 前言 使用命令行程序?qū)Τ绦騿T來說很常見,就算是前端工程師或者開發(fā)gui的,也需要使用命令行來編譯程序或者打包程序 熟練使用命令行工具能極大的提高開發(fā)效率,linux自帶的命令行工具都非常的有用,但是這些工具都是按照通用需求開發(fā)出來的,如果有一些...

    wanghui 評論0 收藏0
  • 【中高級前端必備】手摸手教你擼一個腳手架

    摘要:管理文件當(dāng)前用戶目錄下文件的增刪改查是配置文件是默認(rèn)的配置發(fā)布將本腳手架發(fā)布至上。 腳手架 vue-cli, create-react-app、react-native-cli 等都是非常優(yōu)秀的腳手架,通過腳手架,我們可以快速初始化一個項(xiàng)目,無需自己從零開始一步步配置,有效提升開發(fā)體驗(yàn)。盡管這些腳手架非常優(yōu)秀,但是未必是符合我們的實(shí)際應(yīng)用的,我們可以定制一個屬于自己的腳手架(或公司通用...

    caoym 評論0 收藏0
  • 【許曉笛】從零開始運(yùn)EOS系統(tǒng)

    摘要:成為最早一批運(yùn)行的人復(fù)習(xí)一下上次文章的內(nèi)容,系統(tǒng)主要有三個應(yīng)用程序系統(tǒng)的核心進(jìn)程,也就是所謂的節(jié)點(diǎn)。建立本地單節(jié)點(diǎn)測試網(wǎng)絡(luò)構(gòu)建完成后,我們進(jìn)入目錄使用和命令,運(yùn)行節(jié)點(diǎn)程序命令中,參數(shù)表示使用了賬戶的權(quán)限,這是本地測試系統(tǒng)提供的原始賬戶。 成為最早一批運(yùn)行EOS的人 復(fù)習(xí)一下上次文章的內(nèi)容,EOS 系統(tǒng)主要有三個應(yīng)用程序: nodeos: EOS 系統(tǒng)的核心進(jìn)程,也就是所謂的節(jié)點(diǎn)。 ...

    zoomdong 評論0 收藏0
  • 從零開始學(xué)習(xí) Docker

    摘要:此命令下載測試鏡像并在容器中運(yùn)行它。國內(nèi)很多云服務(wù)商都提供了加速器服務(wù),例如阿里云加速器注冊用戶并且申請加速器,會獲得如這樣的地址。獲取鏡像阿里云鏡像庫上有大量的高質(zhì)量的鏡像可以用,這里我們就說一下怎么獲取這些鏡像并運(yùn)行。 showImg(https://segmentfault.com/img/remote/1460000012924583); 這篇文章是我學(xué)習(xí) Docker 的記錄...

    lily_wang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<