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…

相关文章
相关标签/搜索