50 строк кода, практический проект краулера Node 🕷️

Node.js

предисловие

адрес проекта:Crawler-for-Github-Trending
В основном каждая операция в проекте написана с комментариями, что подходит для студентов, интересующихся сканером Node, чтобы получить базовое представление о нем.

представлять

50 lines, minimalist node crawler for Github Trending.
Поисковый робот на 50 строк, простойaxios, express, cheerioопытный проект.

опыт

Сначала убедитесь, что на компьютере уже установлена ​​среда node10.0+, а затем

1. Вытяните этот проект

git clone https://github.com/poozhu/Crawler-for-Github-Trending.git
cd Crawler-for-Github-Trending
npm i
node index.js

2. Или скачать сжатый пакет этого проекта и разархивировать его

cd Crawler-for-Github-Trending-master  // 进入项目文件夹
npm i
node index.js

Пример

При запуске проекта вы можете увидеть вывод консоли

Listening on port 3000!

В этот момент откройте браузер и войдите в локальную службуhttp://localhost:3000/

http://localhost:3000/time-language // time 表示周期,language 代表语言  例如:

http://localhost:3000/  // 默认抓取今日全部语言的情况
http://localhost:3000/daily  // 代表今日 可选参数:weekly,monthly
http://localhost:3000/daily-JavaScript  // 代表今日的 JavaScript 分类 可选参数:任意语言

После небольшого ожидания вы можете увидеть пример возвращенных данных после сканирования:

[
 {
  "title": "lib-pku / libpku",
  "links": "https://github.com/lib-pku/libpku",
  "description": "贵校课程资料民间整理",
  "language": "JavaScript",
  "stars": "14,297",
  "forks": "4,360",
  "info": "3,121 stars this week"
 },
 {
  "title": "SqueezerIO / squeezer",
  "links": "https://github.com/SqueezerIO/squeezer",
  "description": "Squeezer Framework - Build serverless dApps",
  "language": "JavaScript",
  "stars": "3,212",
  "forks": "80",
  "info": "2,807 stars this week"
 },
 ...
]

Разобрать

Сначала введите зависимости, необходимые сканеру

const cheerio = require('cheerio')   //页面抓取模块,可以像 JQ 一样获取页面的内容
const axios = require('axios');  //请求处理
const express = require('express')  //服务器模块

Адрес запроса сплайсинга

function getData(time, language) {
    //确定好爬取函数所需要的参数后,通过参数的判断来做好请求地址的拼接
    let url = 'https://github.com/trending' + (!!language ? '/' + language : '') + '?since=' + time;
}

Сделать простой запрос на получение

function getData(time, language) {
    let url = 'https://github.com/trending' + (!!language ? '/' + language : '') + '?since=' + time;
    axios.get(url)
        .then(function (response) {
            let html_string = response.data.toString(); 
            const $ = cheerio.load(html_string); // 传递页面到模块
            //此时我们已经可以像用 JQ 一样对获取到的页面 $ 进行元素获取了
            });
        })
        .catch(function (error) {
            console.log(error);
        })
}

Проанализируйте структуру страницы Github Trending и напишите раздел извлечения данных

Можно обнаружить, что список существует под элементом Box, поэтому по этой структуре данные соответствующей позиции можно получить как JQ:

$('.Box .Box-row').each(function () { // 像 jQuery 一样获取对应节点值
    let obj = {};
    obj.title = $(this).find('h1').text().trimStart().trimEnd(); // 获取标题
    obj.links = 'https://github.com/' + obj.title.replace(/\s/g, "");   // 拼接链接
    obj.description = $(this).find('p').text().trimStart().trimEnd();  // 获取获取描述
    obj.language = $(this).find('>.f6 .repo-language-color').siblings().text().trimStart().trimEnd();  // 获取语言
    obj.stars = $(this).find('>.f6 a').eq(0).text().trimStart().trimEnd();  // 获取 start 数
    obj.forks = $(this).find('>.f6 a').eq(1).text().trimStart().trimEnd();  // 获取分支数
    obj.info = $(this).find('>.f6 .float-sm-right').text().trimStart().trimEnd();  // 获取对应时期 star 信息
    obj.avatar = $(this).find('>.f6 img').eq(0).attr('src');  // 获取首位作者头像
}

конфигурация маршрутизации

После выполнения основной функции вам нужно только настроить соответствующий маршрут для получения соответствующих данных и возврата:

const app = express()

//默认抓取页配置
app.get('/', (req, res) => {
    let promise = getData('daily'); // 发起抓取
    promise.then(response => {
        res.json(response); // 数据返回
    });
})

//存在两个参数时
app.get('/:time-:language', (req, res) => {
    const {
        time, // 获取排序时间
        language // 获取对应语言
    } = req.params;
    let promise = getData(time, language); // 发起抓取
    promise.then(response => {
        res.json(response); // 数据返回
    });
})

//存在时间参数时
app.get('/:time', (req, res) => {
    const {
        time, // 获取排序时间
    } = req.params;
    let promise = getData(time); // 发起抓取
    promise.then(response => {
        res.json(response); // 数据返回
    });
})

app.listen(3000, () => console.log('Listening on port 3000!')) // 监听3000端口

Эпилог

Этот проект будет сканировать данные в режиме реального времени каждый раз, когда к ним обращаются, поэтому скорость возврата данных будет очень низкой. Ожидается, что в качестве данных интерфейса следует регулярно сканировать базу данных.

Тем не менее, понимание кода проекта может привести к самым базовым понятиям и принципам использования вышеуказанных узловых модулей и поисковых роботов, и я надеюсь, что это может вам помочь. 😀