В последнее время у меня появился интерес к веб-парсингу, так как я начал замечать, что многие веб-сайты представляют ценную информацию, но не имеют API, чтобы использовать эту информацию любым способом, который мог бы использовать такой любопытный человек, как я.

Поискав в сети, я нашел x-ray, отличный пакет для этой цели, написанный создателем cheerio, и другие рабочие пакеты.

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

Это будет серия, в которой я проведу с ней некоторые эксперименты. Документацию по обсуждаемым мною методам можно найти здесь.

Рейтинг сайта в результатах поиска Google

Допустим, мы хотим найти рейтинг Scavenger в Google.
Для этого мы должны искать наш URL в результатах после разбивки на страницы.

Пагинация

Scavenger предлагает метод .paginateUrl для создания массива URL-адресов с разбивкой на страницы.
Он принимает Object параметров и возвращает Array URL-адресов.

const urls = scavenger.paginateUrl({
        baseUrl: 'https://www.google.com/search?',
        params: {
            q: 'scavenger scraping',
            start: 0
        },
        paginationParam: 'start',
        limit: 20,
        step: 10
    });

Google выполняет этот запрос для разбивки на страницы:
https://www.google.com/search?q=keyword&start=0

Поэтому мы установим для baseUrl значение https://www.google.com/search? »И params, как параметры в строке запроса.
Каждая страница содержит 10 результатов, поэтому мы устанавливаем step на 10 и limit на 20, чтобы останавливаться после второй страницы.
paginationParam просто сообщает Мусорщику, какой параметр увеличивать при смене страницы.

Извлечение результатов

Чтобы извлечь результаты из HTML, очищенного мусорщиком, у нас есть два способа.
Мы можем использовать .extract в html, полученном из .scrape, или сгенерировать функцию для перехода к .scrape с .createExtractor.

Мы воспользуемся вторым подходом, который для меня наиболее понятен.

const extract = scavenger.createExtractor({
    scope: 'div.rc',
    fields: {
        title: 'h3.r a',
        url: {
            selector: 'h3.r a',
            attribute: 'href'
        },
    }
});

Мы передаем объект параметров .createExtractor, который возвращает нам функцию, которую мы позже можем передать .scrape.

Подумайте об этом так:
в JQuery вы бы сделали что-то вроде $(scope).find(title), поэтому каждое поле в fields просматривается, начиная с элемента html, найденного в селекторе scope. По умолчанию для scope установлено значение body.

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

Соскабливание

Итак, теперь у нас есть Array URL-адресов для очистки и Function для извлечения результатов из HTML.
Теперь мы можем позвонить .scrape:

scavenger.scrape(urls, { waitMs: 3000 }, extract)
.then((results) => {
});

Мы также передали Object параметров, чтобы установить waitMs на 3000. Это позволяет нам задерживать каждый запрос на 3 секунды, чтобы избежать слишком быстрой блокировки IP-адресов Google.
results - это Array из Array, каждая из которых представляет результаты для страницы.

В этом случае они выглядят следующим образом:

[
    [
        {
            "title": "scavenger - npm",
            "url": "https://www.npmjs.com/package/scavenger"
        },
        {
            "title": "GitHub - pietrovismara/scavenger: scrape/take screenshots of dynamic ...",
            "url": "https://github.com/pietrovismara/scavenger"
        },
        ...
    ],
    [
        {
            "title": "Price Collapse Hits Scavengers Who Scrape the Bottom of Big Oil's ...",
            "url": "https://www.bloomberg.com/news/articles/2015-01-20/scavengers-pumping-big-oil-s-castoffs-face-grim-choice-amid-rout"
        },
        ...
    ],
    ...
]

Хорошо! Мы видим, что первые 2 рейтинга заняты страницей npm и страницей github Scavenger.
Теперь легко написать функцию, которая сообщает нам, какой рейтинг имеет наш веб-сайт по заданному ключевому слову.

.then((results) => {
    results = [].concat.apply([], pages);
    const ranking = results.findIndex((result) => {
        return result.url === 'https://www.npmjs.com/package/scavenger';
    });
    ranking = ranking === -1 ? ranking : ranking + 1;
    console.log(`Ranking: ${ranking}.`);
    // 1
})

На этом пока все! Вы можете получить полный код здесь. Скоро появятся новые варианты использования, так что следите за обновлениями.

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