国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

手把手教你如何用Crawlab構(gòu)建技術(shù)文章聚合平臺(tái)(一)

LinkedME2016 / 2229人閱讀

摘要:本文將介紹如何使用和抓取主流的技術(shù)博客文章,然后用搭建一個(gè)小型的技術(shù)文章聚合平臺(tái)。是谷歌開源的基于和的自動(dòng)化測(cè)試工具,可以很方便的讓程序模擬用戶的操作,對(duì)瀏覽器進(jìn)行程序化控制。相對(duì)于,是新的開源項(xiàng)目,而且是谷歌開發(fā),可以使用很多新的特性。

背景

說到爬蟲,大多數(shù)程序員想到的是scrapy這樣受人歡迎的框架。scrapy的確不錯(cuò),而且有很強(qiáng)大的生態(tài)圈,有g(shù)erapy等優(yōu)秀的可視化界面。但是,它還是有一些不能做到的事情,例如在頁面上做翻頁點(diǎn)擊操作、移動(dòng)端抓取等等。對(duì)于這些新的需求,可以用Selenium、Puppeteer、Appium這些自動(dòng)化測(cè)試框架繞開繁瑣的動(dòng)態(tài)內(nèi)容,直接模擬用戶操作進(jìn)行抓取??上У氖?,這些框架不是專門的爬蟲框架,不能對(duì)爬蟲進(jìn)行集中管理,因此對(duì)于一個(gè)多達(dá)數(shù)十個(gè)爬蟲的大型項(xiàng)目來說有些棘手。

Crawlab是一個(gè)基于Celery的分布式通用爬蟲管理平臺(tái),擅長(zhǎng)將不同編程語言編寫的爬蟲整合在一處,方便監(jiān)控和管理。Crawlab有精美的可視化界面,能對(duì)多個(gè)爬蟲進(jìn)行運(yùn)行和管理。任務(wù)調(diào)度引擎是本身支持分布式架構(gòu)的Celery,因此Crawlab可以天然集成分布式爬蟲。有一些朋友認(rèn)為Crawlab只是一個(gè)任務(wù)調(diào)度引擎,其實(shí)這樣認(rèn)為并不完全正確。Crawlab是類似Gerapy這樣的專注于爬蟲的管理平臺(tái)。

本文將介紹如何使用Crawlab和Puppeteer抓取主流的技術(shù)博客文章,然后用Flask+Vue搭建一個(gè)小型的技術(shù)文章聚合平臺(tái)。

Crawlab

在前一篇文章《分布式通用爬蟲管理平臺(tái)Crawlab》已介紹了Crawlab的架構(gòu)以及安裝使用,這里快速介紹一下如何安裝、運(yùn)行、使用Crawlab。

安裝

到Crawlab的Github Repo用克隆一份到本地。

git clone https://github.com/tikazyq/crawlab

安裝相應(yīng)的依賴包和庫。

cd crawlab

# 安裝python依賴
pip install -r crawlab/requirements

# 安裝前端依賴
cd frontend
npm install

安裝mongodb和redis-server。Crawlab將用MongoDB作為結(jié)果集以及運(yùn)行操作的儲(chǔ)存方式,Redis作為Celery的任務(wù)隊(duì)列,因此需要安裝這兩個(gè)數(shù)據(jù)庫。

運(yùn)行

在運(yùn)行之前需要對(duì)Crawlab進(jìn)行一些配置,配置文件為config.py。

# project variables
PROJECT_SOURCE_FILE_FOLDER = "/Users/yeqing/projects/crawlab/spiders" # 爬蟲源碼根目錄
PROJECT_DEPLOY_FILE_FOLDER = "/var/crawlab"  # 爬蟲部署根目錄
PROJECT_LOGS_FOLDER = "/var/logs/crawlab"  # 日志目錄
PROJECT_TMP_FOLDER = "/tmp"  # 臨時(shí)文件目錄

# celery variables
BROKER_URL = "redis://192.168.99.100:6379/0"  # 中間者URL,連接redis
CELERY_RESULT_BACKEND = "mongodb://192.168.99.100:27017/"  # CELERY后臺(tái)URL
CELERY_MONGODB_BACKEND_SETTINGS = {
    "database": "crawlab_test",
    "taskmeta_collection": "tasks_celery",
}
CELERY_TIMEZONE = "Asia/Shanghai"
CELERY_ENABLE_UTC = True

# flower variables
FLOWER_API_ENDPOINT = "http://localhost:5555/api"  # Flower服務(wù)地址

# database variables
MONGO_HOST = "192.168.99.100"
MONGO_PORT = 27017
MONGO_DB = "crawlab_test"

# flask variables
DEBUG = True
FLASK_HOST = "127.0.0.1"
FLASK_PORT = 8000

啟動(dòng)后端API,也就是一個(gè)Flask App,可以直接啟動(dòng),或者用gunicorn代替。

cd ../crawlab
python app.py

啟動(dòng)Flower服務(wù)(抱歉目前集成Flower到App服務(wù)中,必須多帶帶啟動(dòng)來獲取節(jié)點(diǎn)信息,后面的版本不需要這個(gè)操作)。

python ./bin/run_flower.py

啟動(dòng)本地Worker。在其他節(jié)點(diǎn)中如果想只是想執(zhí)行任務(wù)的話,只需要啟動(dòng)這一個(gè)服務(wù)就可以了。

python ./bin/run_worker.py

啟動(dòng)前端服務(wù)器。

cd ../frontend
npm run serve
使用

首頁Home中可以看到總?cè)蝿?wù)數(shù)、總爬蟲數(shù)、在線節(jié)點(diǎn)數(shù)和總部署數(shù),以及過去30天的任務(wù)運(yùn)行數(shù)量。

點(diǎn)擊側(cè)邊欄的Spiders或者上方到Spiders數(shù),可以進(jìn)入到爬蟲列表頁。

這些是爬蟲源碼根目錄PROJECT_SOURCE_FILE_FOLDER下的爬蟲。Crawlab會(huì)自動(dòng)掃描該目錄下的子目錄,將子目錄看作一個(gè)爬蟲。Action列下有一些操作選項(xiàng),點(diǎn)擊部署Deploy按鈕將爬蟲部署到所有在線節(jié)點(diǎn)中。部署成功后,點(diǎn)擊運(yùn)行Run按鈕,觸發(fā)抓取任務(wù)。這時(shí),任務(wù)應(yīng)該已經(jīng)在執(zhí)行了。點(diǎn)擊側(cè)邊欄的Tasks到任務(wù)列表,可以看到已經(jīng)調(diào)度過的爬蟲任務(wù)。

基本使用就是這些,但是Crawlab還能做到更多,大家可以進(jìn)一步探索,詳情請(qǐng)見Github。

Puppeteer

Puppeteer是谷歌開源的基于Chromium和NodeJS的自動(dòng)化測(cè)試工具,可以很方便的讓程序模擬用戶的操作,對(duì)瀏覽器進(jìn)行程序化控制。Puppeteer有一些常用操作,例如點(diǎn)擊,鼠標(biāo)移動(dòng),滑動(dòng),截屏,下載文件等等。另外,Puppeteer很類似Selenium,可以定位瀏覽器中網(wǎng)頁元素,將其數(shù)據(jù)抓取下來。因此,Puppeteer也成為了新的爬蟲利器。

相對(duì)于Selenium,Puppeteer是新的開源項(xiàng)目,而且是谷歌開發(fā),可以使用很多新的特性。對(duì)于爬蟲來說,如果前端知識(shí)足夠的話,寫數(shù)據(jù)抓取邏輯簡(jiǎn)直不能再簡(jiǎn)單。正如其名字一樣,我們是在操作木偶人來幫我們抓取數(shù)據(jù),是不是很貼切?

掘金上已經(jīng)有很多關(guān)于Puppeteer的教程了(爬蟲利器 Puppeteer 實(shí)戰(zhàn)、Puppeteer 與 Chrome Headless —— 從入門到爬蟲),這里只簡(jiǎn)單介紹一下Puppeteer的安裝和使用。

安裝

安裝很簡(jiǎn)單,就一行npm install命令,npm會(huì)自動(dòng)下載Chromium并安裝,這個(gè)時(shí)間會(huì)比較長(zhǎng)。為了讓安裝好的puppeteer模塊能夠被所有nodejs爬蟲所共享,我們?cè)?b>PROJECT_DEPLOY_FILE_FOLDER目錄下安裝node的包。

# PROJECT_DEPLOY_FILE_FOLDER變量值
cd /var/crawlab

# 安裝puppeteer
npm i puppeteer

# 安裝mongodb
npm i mongodb

安裝mongodb是為了后續(xù)的數(shù)據(jù)庫操作。

使用

以下是Copy/Paste的一段用Puppeteer訪問簡(jiǎn)書然后截屏的代碼,非常簡(jiǎn)潔。

const puppeteer = require("puppeteer");

(async () => {
  const browser = await (puppeteer.launch());
  const page = await browser.newPage();
  await page.goto("https://www.jianshu.com/u/40909ea33e50");
  await page.screenshot({
    path: "jianshu.png",
    type: "png",
    // quality: 100, 只對(duì)jpg有效
    fullPage: true,
    // 指定區(qū)域截圖,clip和fullPage兩者只能設(shè)置一個(gè)
    // clip: {
    //   x: 0,
    //   y: 0,
    //   width: 1000,
    //   height: 40
    // }
  });
  browser.close();
})();

關(guān)于Puppeteer的常用操作,請(qǐng)移步《我常用的puppeteer爬蟲api》。

編寫爬蟲

啰嗦了這么久,終于到了萬眾期待的爬蟲時(shí)間了。Talk is cheap, show me the code!咦?我們不是已經(jīng)Show了不少代碼了么...

由于我們的目標(biāo)是建立一個(gè)技術(shù)文章聚合平臺(tái),我們需要去各大技術(shù)網(wǎng)站抓取文章。資源當(dāng)然是越多越好。作為展示用,我們將抓取下面幾個(gè)具有代表性的網(wǎng)站:

掘金

SegmentFault

CSDN

研究發(fā)現(xiàn)這三個(gè)網(wǎng)站都是由Ajax獲取文章列表,生成動(dòng)態(tài)內(nèi)容以作為傳統(tǒng)的分頁替代。這對(duì)于Puppeteer來說很容易處理,因?yàn)镻uppeteer繞開了解析Ajax這一部分,瀏覽器會(huì)自動(dòng)處理這樣的操作和請(qǐng)求,我們只著重關(guān)注數(shù)據(jù)獲取就行了。三個(gè)網(wǎng)站的抓取策略基本相同,我們以掘金為例著重講解。

掘金

首先是引入Puppeteer和打開網(wǎng)頁。

const puppeteer = require("puppeteer");
const MongoClient = require("mongodb").MongoClient;

(async () => {
  // browser
  const browser = await (puppeteer.launch({
    headless: true
  }));

  // define start url
  const url = "https://juejin.im";

  // start a new page
  const page = await browser.newPage();
  
  ...
  
})();

headless設(shè)置為true可以讓瀏覽器以headless的方式運(yùn)行,也就是指瀏覽器不用在界面中打開,它會(huì)在后臺(tái)運(yùn)行,用戶是看不到瀏覽器的。browser.newPage()將新生成一個(gè)標(biāo)簽頁。后面的操作基本就圍繞著生成的page來進(jìn)行。

接下來我們讓瀏覽器導(dǎo)航到start url。

  ...
  
  // navigate to url
  try {
    await page.goto(url, {waitUntil: "domcontentloaded"});
    await page.waitFor(2000);
  } catch (e) {
    console.error(e);

    // close browser
    browser.close();

    // exit code 1 indicating an error happened
    code = 1;
    process.emit("exit ");
    process.reallyExit(code);

    return
  }
  
  ...

這里try catch的操作是為了處理瀏覽器訪問超時(shí)的錯(cuò)誤。當(dāng)訪問超時(shí)時(shí),設(shè)置exit code1表示該任務(wù)失敗了,這樣Crawlab會(huì)將該任務(wù)狀態(tài)設(shè)置為FAILURE

然后我們需要下拉頁面讓瀏覽器可以讀取下一頁。

  ...
  
  // scroll down to fetch more data
  for (let i = 0; i < 100; i++) {
    console.log("Pressing PageDown...");
    await page.keyboard.press("PageDown", 200);
    await page.waitFor(100);
  }
  
  ...

翻頁完畢后,就開始抓取數(shù)據(jù)了。

  ...
  // scrape data
  const results = await page.evaluate(() => {
    let results = [];
    document.querySelectorAll(".entry-list > .item").forEach(el => {
      if (!el.querySelector(".title")) return;
      results.push({
        url: "https://juejin.com" + el.querySelector(".title").getAttribute("href"),
        title: el.querySelector(".title").innerText
      });
    });
    return results;
  });
  ...

page.evaluate可以在瀏覽器Console中進(jìn)行JS操作。這段代碼其實(shí)可以直接在瀏覽器Console中直接運(yùn)行。調(diào)試起來是不是方便到爽?前端工程師們,開始?xì)g呼吧!

獲取了數(shù)據(jù),接下來我們需要將其儲(chǔ)存在數(shù)據(jù)庫中。

  ...
  
  // open database connection
  const client = await MongoClient.connect("mongodb://192.168.99.100:27017");
  let db = await client.db("crawlab_test");
  const colName = process.env.CRAWLAB_COLLECTION || "results_juejin";
  const taskId = process.env.CRAWLAB_TASK_ID;
  const col = db.collection(colName);

  // save to database
  for (let i = 0; i < results.length; i++) {
    // de-duplication
    const r = await col.findOne({url: results[i]});
    if (r) continue;

    // assign taskID
    results[i].task_id = taskId;

    // insert row
    await col.insertOne(results[i]);
  }
  
  ...

這樣,我們就將掘金最新的文章數(shù)據(jù)保存在了數(shù)據(jù)庫中。其中,我們用url字段做了去重處理。CRAWLAB_COLLECTIONCRAWLAB_TASK_ID是Crawlab傳過來的環(huán)境變量,分別是儲(chǔ)存的collection和任務(wù)ID。任務(wù)ID需要以task_id為鍵保存起來,這樣在Crawlab中就可以將數(shù)據(jù)與任務(wù)關(guān)聯(lián)起來了。

整個(gè)爬蟲代碼如下。

const puppeteer = require("puppeteer");
const MongoClient = require("mongodb").MongoClient;

(async () => {
  // browser
  const browser = await (puppeteer.launch({
    headless: true
  }));

  // define start url
  const url = "https://juejin.im";

  // start a new page
  const page = await browser.newPage();

  // navigate to url
  try {
    await page.goto(url, {waitUntil: "domcontentloaded"});
    await page.waitFor(2000);
  } catch (e) {
    console.error(e);

    // close browser
    browser.close();

    // exit code 1 indicating an error happened
    code = 1;
    process.emit("exit ");
    process.reallyExit(code);

    return
  }

  // scroll down to fetch more data
  for (let i = 0; i < 100; i++) {
    console.log("Pressing PageDown...");
    await page.keyboard.press("PageDown", 200);
    await page.waitFor(100);
  }

  // scrape data
  const results = await page.evaluate(() => {
    let results = [];
    document.querySelectorAll(".entry-list > .item").forEach(el => {
      if (!el.querySelector(".title")) return;
      results.push({
        url: "https://juejin.com" + el.querySelector(".title").getAttribute("href"),
        title: el.querySelector(".title").innerText
      });
    });
    return results;
  });

  // open database connection
  const client = await MongoClient.connect("mongodb://192.168.99.100:27017");
  let db = await client.db("crawlab_test");
  const colName = process.env.CRAWLAB_COLLECTION || "results_juejin";
  const taskId = process.env.CRAWLAB_TASK_ID;
  const col = db.collection(colName);

  // save to database
  for (let i = 0; i < results.length; i++) {
    // de-duplication
    const r = await col.findOne({url: results[i]});
    if (r) continue;

    // assign taskID
    results[i].task_id = taskId;

    // insert row
    await col.insertOne(results[i]);
  }

  console.log(`results.length: ${results.length}`);

  // close database connection
  client.close();

  // shutdown browser
  browser.close();
})();
SegmentFault & CSDN

這兩個(gè)網(wǎng)站的爬蟲代碼基本與上面的爬蟲一樣,只是一些參數(shù)不一樣而已。我們的爬蟲項(xiàng)目結(jié)構(gòu)如下。

運(yùn)行爬蟲

在Crawlab中打開Spiders,我們可以看到剛剛編寫好的爬蟲。

點(diǎn)擊各個(gè)爬蟲的View查看按鈕,進(jìn)入到爬蟲詳情。

在Execute Command中輸入爬蟲執(zhí)行命令。對(duì)掘金爬蟲來說,是node juejin_spider.js。輸入完畢后點(diǎn)擊Save保存。然后點(diǎn)擊Deploy部署爬蟲。最后點(diǎn)擊Run運(yùn)行爬蟲。

點(diǎn)擊左上角到刷新按鈕可以看到剛剛運(yùn)行的爬蟲任務(wù)已經(jīng)在運(yùn)行了。點(diǎn)擊Create Time后可以進(jìn)入到任務(wù)詳情。Overview標(biāo)簽中可以看到任務(wù)信息,Log標(biāo)簽可以看到日志信息,Results信息中可以看到抓取結(jié)果。目前在Crawlab結(jié)果列表中還不支持?jǐn)?shù)據(jù)導(dǎo)出,但是不久的版本中肯定會(huì)將導(dǎo)出功能加入進(jìn)來。

總結(jié)

在這一小節(jié),我們已經(jīng)能夠?qū)rawlab運(yùn)行起來,并且能用Puppeteer編寫抓取三大網(wǎng)站技術(shù)文章的爬蟲,并且能夠用Crawlab運(yùn)行爬蟲,并且讀取抓取后的數(shù)據(jù)。下一節(jié),我們將用Flask+Vue做一個(gè)簡(jiǎn)單的技術(shù)文章聚合網(wǎng)站。能看到這里的都是有耐心的好同學(xué),贊一個(gè)。

Github: tikazyq/crawlab

如果感覺Crawlab還不錯(cuò)的話,請(qǐng)加作者微信拉入開發(fā)交流群,大家一起交流關(guān)于Crawlab的使用和開發(fā)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102578.html

相關(guān)文章

  • 把手你如何用Crawlab構(gòu)建技術(shù)文章聚合平臺(tái)(二)

    摘要:上一篇文章手把手教你如何用構(gòu)建技術(shù)文章聚合平臺(tái)一介紹了如何使用搭建的運(yùn)行環(huán)境,并且將與集成,對(duì)掘金進(jìn)行技術(shù)文章的抓取,最后可以查看抓取結(jié)果。本篇文章將繼續(xù)講解如何利用編寫一個(gè)精簡(jiǎn)的聚合平臺(tái),將抓取好的文章內(nèi)容展示出來。 上一篇文章《手把手教你如何用Crawlab構(gòu)建技術(shù)文章聚合平臺(tái)(一)》介紹了如何使用搭建Crawlab的運(yùn)行環(huán)境,并且將Puppeteer與Crawlab集成,對(duì)掘金、...

    zhunjiee 評(píng)論0 收藏0
  • 把手你如何用Crawlab構(gòu)建技術(shù)文章聚合平臺(tái)()

    摘要:本文將介紹如何使用和抓取主流的技術(shù)博客文章,然后用搭建一個(gè)小型的技術(shù)文章聚合平臺(tái)。是谷歌開源的基于和的自動(dòng)化測(cè)試工具,可以很方便的讓程序模擬用戶的操作,對(duì)瀏覽器進(jìn)行程序化控制。相對(duì)于,是新的開源項(xiàng)目,而且是谷歌開發(fā),可以使用很多新的特性。 背景 說到爬蟲,大多數(shù)程序員想到的是scrapy這樣受人歡迎的框架。scrapy的確不錯(cuò),而且有很強(qiáng)大的生態(tài)圈,有g(shù)erapy等優(yōu)秀的可視化界面。但...

    Jeffrrey 評(píng)論0 收藏0
  • 爬蟲平臺(tái)Crawlab v0.2發(fā)布

    摘要:是一個(gè)專注于爬蟲的集成了爬蟲管理任務(wù)調(diào)度任務(wù)監(jiān)控?cái)?shù)據(jù)分析等模塊的分布式爬蟲管理平臺(tái),非常適合對(duì)爬蟲管理爬蟲工程化有要求的開發(fā)者及企業(yè)。從目前開源的框架來看,大部分爬蟲平臺(tái)是以為核心,因此只能支持框架的爬蟲,而不僅支持,還支持其他框架的爬蟲。 showImg(https://segmentfault.com/img/remote/1460000019143107?w=2559&h=112...

    yiliang 評(píng)論0 收藏0
  • [爬蟲手記] 我是如何在3分鐘內(nèi)開發(fā)完個(gè)爬蟲的

    摘要:前言開發(fā)爬蟲是一件有趣的事情。的可配置爬蟲是基于的,因此天生是支持并發(fā)的。遵守協(xié)議這個(gè)默認(rèn)是開啟的。的可配置爬蟲降低了爬蟲的開發(fā)時(shí)間,增加了爬蟲開發(fā)效率,完善了工程化水平,將爬蟲工程師從日常的繁瑣配置工作中解放出來。 前言 開發(fā)爬蟲是一件有趣的事情。寫一個(gè)程序,對(duì)感興趣的目標(biāo)網(wǎng)站發(fā)起HTTP請(qǐng)求,獲取HTML,解析HTML,提取數(shù)據(jù),將數(shù)據(jù)保存到數(shù)據(jù)庫或者存為CSV、JSON等格式,再...

    sushi 評(píng)論0 收藏0
  • [爬蟲手記] 我是如何在3分鐘內(nèi)開發(fā)完個(gè)爬蟲的

    摘要:前言開發(fā)爬蟲是一件有趣的事情。的可配置爬蟲是基于的,因此天生是支持并發(fā)的。的可配置爬蟲降低了爬蟲的開發(fā)時(shí)間,增加了爬蟲開發(fā)效率,完善了工程化水平,將爬蟲工程師從日常的繁瑣配置工作中解放出來。前言 開發(fā)爬蟲是一件有趣的事情。寫一個(gè)程序,對(duì)感興趣的目標(biāo)網(wǎng)站發(fā)起HTTP請(qǐng)求,獲取HTML,解析HTML,提取數(shù)據(jù),將數(shù)據(jù)保存到數(shù)據(jù)庫或者存為CSV、JSON等格式,再用自己熟悉的語言例如Python對(duì)...

    YorkChen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<