Рептилии, это на самом деле так просто

рептилия JavaScript
Рептилии, это на самом деле так просто

Впитай то, чего у меня нет, поделись тем, что у меня есть

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

Недавно я также узнал о краулерах, потому что данные о метро, ​​которые мне нужно было использовать в предыдущем проекте, были не данными, которые были просканированы краулерами, а были скопированы напрямую.

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

Во-первых, поговорим оПротокол Crawler и Robotsчто

Затем введитеОсновной процесс сканирования

Наконец, поднимитесь на один по настоящему каштану.Недавно выпущенные фильмы ДубанаДавай попробуем нож

Протокол Crawler и Robots

Сначала посмотрите на определение:рептилия, это программа, которая автоматически получает содержимое веб-страниц. Это важная часть поисковых систем, поэтому поисковая оптимизация в значительной степени оптимизирована для поисковых роботов.

посмотри сноваПротокол роботоввведение,robots.txtэто текстовый файл, robots.txt это протокол, а не команда

robots.txt эторептилияхотетьПроверятьизПервыйфайл, robots.txt сообщает краулеру, какие файлы можно просматривать на сервере, а робот-краулер определяет область доступа в соответствии с содержимым файла

На картинке нижеДубан фильмОбласть доступа указана на странице о протоколе robots.

Протоколы поисковых роботов и роботов тесно связаны между собой. Если вы видите страницы, сканирование которых запрещено, не сканируйте их. Если затронуты какие-то аспекты конфиденциальности пользователей, они будут обнаружены и переданы в законные каналы позже.

Таким образом, все в отрасли согласны с этим протоколом роботов.Если вы не хотите лазить по страницам, не ползайте, и Интернет может быть мирным.

Это немного не так, давайте посмотрим на картинку ниже, давайте сделаем это прощегребеньчто сказано выше

На самом деле, спросят некоторые люди, в конце концов, рептилиячто такое восхождение?

Это очень проницательный вопрос.. Грубо говоря, абзац, который получил краулер, этоHTML-код, так что это нам не чуждо, пока мы выражаемсяПреобразование в дерево DOMпросто хорошо

Итак, теперь, взглянув на правую половину рисунка выше, этоСравнительная таблица

левыйданетограниченноеПротокол роботовДа, разумно сказать, что три папки admin/private и tmp не могут быть захвачены, но поскольку нет протокола Robots, люди могут беспринципно ползать

посмотри сноваправильноограниченоПротокол роботовДа, в отличие от поисковых систем, таких как Googleчерез robots.txtПерейдите к файлу, чтобы увидеть, какие из них не могут быть захвачены, а затем пропустите его напрямую, когда вы переходите к администратору или частному, и не захватывайте его.

Ладно, это все для введения Все, что не включает в себя настоящие ножи и настоящие пистолеты, просто болтовня на бумаге.

Основной процесс сканирования

На самом деле, для использования краулеров процесс представляет собой не что иное, как эти четыре шага.

  1. посвятить данные
  2. Хранилище данных
  3. запустить службу
  4. визуализировать данные

посвятить данные

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

Давайте сначала посмотрим на общую структуру каталогов.

так как этопосвятить данные, мы должны использовать более известный в отраслиартефакт------request

артефакт запроса

Итак, как использовать запрос, давайте слушать ветер и смотреть код вместе

// 使用起来超简单
let request = require('request');

request('http://www.baidu.com', function (error, response, body) {
    console.log('error:', error); // 当有错误发生时打印错误日志
    console.log('statusCode:', response && response.statusCode); // 打印响应状态码
    console.log('body:', body); // 打印百度页面的html代码
});

Прочитав приведенный выше код, вам все еще не кажется, что это не очевидно. друг,HTML-кодОн уже появился перед вами, так что не сдерживайтесь, пока вы обращаетесь к знакомому ДОМу, вы можете делать все, что хотите

Итак, Cheerio дебютировал, и все называли его Node-версией jq. Вы можете полностью управлять DOM по привычке jq.

Больше никаких обходных путей внизу, давайте писать гадов вместе!

читать содержимое

Домашняя страница должна сначала проанализировать страницы Douban Movies, которые являются самыми популярными фильмами, давайте сначала посмотримDOMструктура

Ну и после прочтения тиофена, нужный нам контент тоже помечается, далее входим в файл read.js, и начинаем его вылизывать в один прием.

// read.js文件

// request-promise是让request支持了promise的语法,可以说是request的小弟
const rp = require('request-promise');
// 将抓取页面的html代码转为DOM,可以称之为是node版的jq
const cheerio = require('cheerio');
// 这个是为了在调试时查看日志
const debug = require('debug')('movie:read');

// 读取页面的方法,重点来了
const read = async (url) => {
    debug('开始读取最近上映的电影');

    const opts = {
        url,    // 目标页面
        transform: body => {
            // body为目标页面抓取到的html代码
            // 通过cheerio.load方法可以把html代码转换成可以操作的DOM结构
            return cheerio.load(body);
        }
    };

    return rp(opts).then($ => {
        let result = [];    // 结果数组
        // 遍历这些热映电影的li
        $('#screening li.ui-slide-item').each((index, item) => {
            let ele = $(item);
            let name = ele.data('title');
            let score = ele.data('rate') || '暂无评分';
            let href = ele.find('.poster a').attr('href');
            let image = ele.find('img').attr('src');
            // 影片id可以从影片href中获取到
            let id = href && href.match(/(\d+)/)[1];
            // 为了防止豆瓣防盗链导致裂图,换成webp格式加载图片
            image = image && image.replace(/jpg$/, 'webp');

            if (!name || !image || !href) {
                return;
            }

            result.push({
                name,
                score,
                href,
                image,
                id
            });
            debug(`正在读取电影:${name}`);
        });
        // 返回结果数组
        return result;
    });
};
// 导出方法
module.exports = read;

После написания кода давайте вспомним, что вы сделали.

  • пройти черезrequestвзял html код
  • cheerioКонвертировать html в dom
  • контент, который будет нуженмассив существует(имя|рейтинг|адрес|картинка|id)
  • возвращает массив результатов иЭкспорт метода чтения

Хранилище данных

Здесь мы проходимmysqlЧтобы создать базу данных для хранения данных, не имеет значения, если вы мало знаете, позвольте мне сначала сделать это шаг за шагом. Давайте сначала установимXAMPPиNavicatВизуальный инструмент управления базами данных, после установки выполните следующие действия.

XAMPP запускает mysql

Navicat подключается к базе данных и создает таблицу

Несколько слов могут быть не такими реальными, как есть фотографии и правда.Давайте сначала посмотрим на картинки.

Что ж, эпоха чтения картинок подошла к концу. Мне очень стыдно потреблять много трафика. Вернемся к этапу кодирования.

Подключиться к базе данных

Прежде всего, нам нужно создать sql-файл в каталоге src, который имеет то же имя, что и база данных, которую мы только что создали, поэтому назовите его my_movie.sql (разумеется, структура каталога уже создана)

Затем вернитесь к файлу db.js и напишите код для подключения к базе данных.

// db.js

const mysql = require('mysql');
const bluebird = require('bluebird');

// 创建连接
const connection = mysql.createConnection({
    host: 'localhost',      // host
    port: 3306,             // 端口号默认3306
    database: 'my_movie',   // 对应的数据库
    user: 'root',
    password: ''
});

connection.connect();  // 连接数据库

// bluebird是为了方便支持promise语法化
// 然后直接把数据库的query查询语句导出方便之后调用
module.exports = bluebird.promisify(connection.query).bind(connection);

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

записать в базу данных

На этот раз давайте посмотрим на файл write.js, Да, как следует из названия, он используется для записи в базу данных, непосредственно в коде

// write.js文件

// 从db.js那里导入query方法
const query = require('./db');
const debug = require('debug')('movie:write');
// 写入数据库的方法
const write = async (movies) => {
    debug('开始写入电影');
    
    // movies即为read.js读取出来的结果数组
    for (let movie of movies) {
        // 通过query方法去查询一下是不是已经在数据库里存过了
        let oldMovie = await query('SELECT * FROM movies WHERE id=? LIMIT 1', [movie.id]);
        
        // sql查询语句返回的是一个数组,如果不为空数组的话就表示有数据存过
        // 直接就进行更新操作了
        if (Array.isArray(oldMovie) && oldMovie.length) {
            // 更新movies表里的数据
            let old = oldMovie[0];
            await query('UPDATE movies SET name=?,href=?,image=?,score=? WHERE id=?', [movie.name, movie.href, movie.image, movie.score, old.id]);
        } else {
            // 插入内容到movies表
            await query('INSERT INTO movies(id,name,href,image,score) VALUES(?,?,?,?,?)', [movie.id, movie.name, movie.href, movie.image, movie.score]);
        }

        debug(`正在写入电影:${movie.name}`);
    }
};

module.exports = write;

Написание вышеизложенного может немного сбивать с толку, в конце концов, чистый интерфейс редко пишет операторы SQL. Но не стесняйтесь, я кратко представлю часть оператора SQL после того, как сначала разберусь с приведенным выше кодом.

Что именно написано в write.js?

  • Познакомить с методом запроса для написания операторов SQL.
  • Итерация по массиву результатов чтения
  • Запросить, сохранены ли данные
    • с: обновить данные
    • нет: вставить данные

Ну и способ записи в БД тоже реализован выше, дальше куй железо, пока горячо, и немного поговорим о SQL-операторах.

Изучение операторов SQL

? указывает заполнитель Здесь, кстати, вкратце расскажу о синтаксисе, который будет использоваться в операторах SQL, которые распространены повсеместно.CRUD

  1. вставить данные
语法: 
    INSERT INTO 表名(列名) VALUES(列名值)
栗子:
    INSERT INTO tags(name,id,url) VALUES('爬虫',10,'https://news.so.com/hotnews')
解释:
    向标签表(tags)里插入一条,姓名,id和访问地址分别为VALUES内对应的值
  1. обновить данные
语法:
    UPDATE 表名 SET 列名=更新值 WHERE 更新条件
栗子:
    UPDATE articles SET title='你好,世界',content='世界没你想的那么糟!' WHERE id=1
解释:
    更新id为1的文章,标题和内容都进行了修改
  1. удалить данные
语法:
    DELETE FROM 表名 WHERE 删除条件
栗子:
    DELETE FROM tags WHERE id=11
解释:
    从标签表(tags)里删除id为11的数据
  1. Запрос
语法:
    SELECT 列名 FROM 表名 WHERE 查询条件 ORDER BY 排序列名
栗子:
    SELECT name,title,content FROM tags WHERE id=8
解释:
    查询id为8的标签表里对应信息

К этому моменту я написал все методы чтения и записи, так что все должны быть немного утомлены. Пора тестировать результаты, а то это все фигня

выполнять операции чтения и записи

Теперь перейдите к index.js и начните его тестировать.

// index.js文件

const read = require('./read');
const write = require('./write');
const url = 'https://movie.douban.com'; // 目标页面

(async () => {
    // 异步抓取目标页面
    const movies = await read(url);
    // 写入数据到数据库
    await write(movies);
    // 完毕后退出程序
    process.exit();
})();

Готово, запустите его, чтобы увидеть, каков эффект, перейдите прямо к картинке выше.

Код выполнился, вернемся в Navicat и посмотрим, записались ли данные.
На данный момент мы завершили операции по сбору и хранению данных, но чего нам не хватает?

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

запустить службу

Поскольку мы собираемся создать веб-сервис, давайте начнем писать содержимое server.js.

служба сервера

// server.js文件

const express = require('express');
const path = require('path');
const query = require('../src/db');
const app = express();

// 设置模板引擎
app.set('view engine', 'html');
app.set('views', path.join(__dirname, 'views'));
app.engine('html', require('ejs').__express);

// 首页路由
app.get('/', async (req, res) => {
    // 通过SQL查询语句拿到库里的movies表数据
    const movies = await query('SELECT * FROM movies');
    // 渲染首页模板并把movies数据传过去
    res.render('index', { movies });
});
// 监听localhost:9000端口
app.listen(9000);

После написания серверной службы давайте взглянем на шаблон index.html Это последнее дело После написания все готово.

визуализировать данные

// index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>热映的电影</title>
</head>
<body>
    <div class="container">
        <h2 class="caption">正在热映的电影</h2>
        <ul class="list">
            <% for(let i=0;i<movies.length;i++){ 
                let movie = movies[i];  
            %>
                <li>
                    <a href="<%=movie.href%>" target="_blank">
                        <img src="<%=movie.image%>" />
                        <p class="title"><%=movie.name%></p>
                        <p class="score">评分:<%=movie.score%></p>
                    </a>
                </li>
            <% } %>
        </ul>
    </div>
</body>
</html>

Пройдите массив фильмов через механизм шаблонов, а затем визуализируйте его.

Теперь посмотрите на окончательный эффект

Это судьба, что я пришел сюда со мной.Я очень счастлив, что испытал такую ​​длинную статью, чтобы узнать.Каждый должен иметь хорошее представление о знаниях о рептилиях.

Опубликовать здеськод, чтобы каждый мог обратиться к тук-тук-тук

Спасибо за просмотр, 886