Node爬蟲應用的實踐

Welcome to nodecrawler 👋

     
 
     
 
     
 

node 爬蟲筆記node

🏠 Homepage

1、什麼是爬蟲?

爬蟲簡而言之就是爬去網頁上的信息。而網頁結構就是一個樹形結構,就像一個蜘蛛網同樣。而爬蟲程序就像一個蜘蛛,在這個蜘蛛網上去收取咱們感興趣的信息。jquery

2、開始寫爬蟲前須要肯定的兩個東西。

  1. Where to crawler? (要爬那的信息?)。
  2. What to crawler? (你要爬什麼信息?)。

工藝利其事必先利器git

剛開始找了幾個 node 爬蟲庫,可是效果不是很理想。不過皇天不負有心人,不過最終仍是讓我找到了一個:Apify.github

3、使用 Apify 來開始個人爬蟲之旅

1. 首先新建一個工程而後安裝 apify 依賴。

npm i apify -S
複製代碼

接下來要肯定一下爬取那個網站的信息(以豆瓣電影 Top 250 爲例)sql

2.如今咱們已經肯定了要爬取的 url(movie.douban.com/top250),如今開始編寫代碼。

// 引入apify
  const Apify = require('apify');
複製代碼

3.apify 提供了一個動態隊列(requestQueue)來管理咱們要爬取的 url,咱們可使用它來管理咱們全部要爬取的 url。

const Apify = require('apify');
  Apify.main(async ()=>{
    // 首先建立一個請求隊列
    const requestQueue = await Apify.openRequestQueue();
    // 將要爬取的url添加到隊列當中
    await requestQueue.addRequest('https://movie.douban.com/top250');
  })
複製代碼

5.已經有了請求隊列,接下來要作的是What to crawler。須要一個方法去解析請求的網頁內容。

定義一個函數來解析網頁內容,該函數以後會傳入apify爬蟲的一個實例當中數據庫

async function handlePageFunction({ request, $ }) {
    // 是否是對$很熟悉,其實就是node裏的jquery
    // 先簡單打印下網頁的title.
    const title = $('title').text();
    console.log(`網頁的title:${title}`);
}
複製代碼

6.最後,建立一個CheerioCrawler 爬蟲實例,並將requestQueue,handlePageFunction做爲參數傳入。而後啓動爬蟲

const crawler = new Apify.CheerioCrawler({
        requestQueue,
        handlePageFunction
  })

  // 啓動爬蟲
  await crawler.run();
複製代碼

咱們把代碼作一下整合,而後啓動爬蟲。npm

const Apify = require('apify');


  Apify.main(async () => {
      // 建立請求隊列
      const requestQueue = await Apify.openRequestQueue();
      // 將要爬取的url添加到隊列當中
      await requestQueue.addRequest({ url: 'https://movie.douban.com/top250' });

      const handlePageFunction = async ({ request, $ }) => {
          // 是否是對$很熟悉,其實就是node裏的jquery
          // 先簡單打印下網頁的title.
          const title = $('title').text();
          console.log(`網頁的title:${title}`);
      }

      //建立一個CheerioCrawler,將requestQueue,handlePageFunction做爲參數傳入
      const crawler = new Apify.CheerioCrawler({
          requestQueue,
          handlePageFunction
      })
      // 啓動爬蟲
      await crawler.run();
  })
複製代碼

運行代碼,頁面的標題成功被爬取api

到這裏,就已經實現了一個簡易的爬蟲,可是尚未實現咱們的需求(爬取完整的top250)。咱們須要動態的去添加url,才能爬取到完整的250部電影。bash

8.獲取全部要爬取的頁面

初始url是首頁,咱們須要獲取全部頁碼的頁面,經過解析頁面,咱們能夠經過以apify提供的一個動態添加url到隊列的方法來將咱們想要爬去的頁面添加到請求隊列當中。async

const {
  utils: { enqueueLinks },
} = Apify;
複製代碼
await enqueueLinks({
            $,
            requestQueue, 
            selector: '.next > a', // 跳轉到下一頁的a標籤
            baseUrl: request.loadedUrl, //根據baseUrl會將a中的href補全
      });
複製代碼

9. 接下來須要修改一下handlePageFunction,來解析須要的電影信息。

/**
 * 解析網頁,獲取電影信息
 */
function parseMovie($) {
    const movieDoms = $('.grid_view .item');
    const movies = [];
    movieDoms.each((index, item) => {
        const movie = {
            rank: $(item).find('.pic em').text(), // 排名
            name: $(item).find('.title').text(), // 電影名
            score: $(item).find('.rating_num').text(), // 評分
            sketch: $(item).find('.inq').text() // 主題
        }
        movies.push(movie)
    })
    return movies
}
複製代碼

10. 再把代碼整合到一塊兒,運行看看結果

const Apify = require('apify');
const {
    utils: { enqueueLinks },
} = Apify;
Apify.main(async () => {
    // 首先建立一個請求隊列
    const requestQueue = await Apify.openRequestQueue();
    await requestQueue.addRequest({ url: 'https://movie.douban.com/top250' });
    const crawler = new Apify.CheerioCrawler({
        requestQueue,
        handlePageFunction
    })
    async function handlePageFunction({ request, $ }) {
        await enqueueLinks({
            $,
            requestQueue,
            selector: '.next > a', // 跳轉到下一頁的a標籤
            baseUrl: request.loadedUrl, //根據baseUrl會將a中的href補全
        });
        const movies = parseMovie($);
        movies.forEach((item, i) => {
            console.log(`${item.rank}|${item.name}|${item.score}|${item.sketch}`)
        })
    }
    // 啓動爬蟲
    await crawler.run();
})





/**
 * 解析網頁,獲取電影信息
 */
function parseMovie($) {
    const movieDoms = $('.grid_view .item');
    const movies = [];
    movieDoms.each((index, item) => {
        const movie = {
            rank: $(item).find('.pic em').text(), // 排名
            name: $(item).find('.title').text(), // 電影名
            score: $(item).find('.rating_num').text(), // 評分
            sketch: $(item).find('.inq').text() // 主題
        }
        movies.push(movie)
    })
    return movies
}
複製代碼

⭐️運行下看看結果

如今的運行結果已經知足咱們的需求了,可是會不會以爲上面的代碼有些麻煩,得找到連接、再轉換、再添加到請求隊列。可不能夠給出一個url規則,而後程序自動幫我添加到隊列中呢?

5、本地數據持久化

這裏咱們使用sqlite來作本地數據持久化,由於它是一個輕量級的數據庫、並且是不須要服務端的。

  1. 安裝sqlite3依賴
npm i sqlite3 -S
複製代碼
  1. 初始化數據庫,建立movies表
const sqlite3 = require('sqlite3').verbose();
function initDB(){
    let db = new sqlite3.Database('./db/crawler.db', (err) => {
        if (err) {
          return console.error(err.message,'啊哈');
        }
        console.log('Connected to the crawler database.');
      });
      createTable(db);
      return db;
}

function createTable(db){
    const sql = `CREATE TABLE  IF NOT EXISTS movies(
        rank TEXT,
        name TEXT,
        TEXT TEXT,
        sketch TEXT
     );`
     db.run(sql,[],(err)=>{
         if(err){
             return console.log(err)
         }
         console.log('表建立成功')
     })
}

複製代碼

3.插入數據

function insertData(db, movie = {}) {
    db.serialize(function () {
        db.run(`INSERT INTO movies(rank,name,score,sketch) VALUES(?,?,?,?)`, [movie.rank, movie.name, movie.score, movie.sketch], function (err) {
            if (err) {
                return console.log(err.message);
            }
            // get the last insert id
            console.log(`A row has been inserted with rowid ${this.lastID}`);
        });
    })
}
複製代碼

結尾

到這裏,一個簡單的爬蟲程序算是寫完了,可是這裏還少了ip代理以及請求源假裝。後面再加上

代碼地址:github.com/hp0844182/n…

相關文章
相關標籤/搜索