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

Возможно, вы слышали о терминах «Веб-скрейпинг» или «Кукловод» и о том, какие классные вещи вы можете с ним делать, вы также хотите узнать больше и даже узнать, как сразу же приступить к работе с ним.

Может быть много причин, по которым вам нужно парсить веб-страницы с помощью Nodejs, например:

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

Существует множество причин для изучения веб-скрейпинга и того, как делать веб-скраппинг с помощью JavaScript и Nodejs.

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

Я покажу вам пример, показывающий, как я парсил веб-сайт мероприятия с помощью Nodejs и Puppeteer.

Вы также узнаете все советы и рекомендации, чтобы овладеть искусством веб-скрапинга и сбора любых данных, которые вы хотите, с помощью Nodejs и Puppeteer.

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



Что такое Кукловод?

Puppeteer — это библиотека Node от Google, которая используется для очистки веб-страниц, а также для управления экземпляром хрома из Node.js.

Есть тысячи вещей, которые вы можете делать с Puppeteer, например:

  1. Парсинг веб-страниц и анализ данных.
  2. Отслеживание производительности загрузки страниц и аналитических данных.
  3. Может использоваться для автоматизации отправки форм.
  4. Puppeteer можно настроить для создания скриншотов страниц.
  5. Его также можно использовать для создания PDF страниц веб-сайта.
  6. Puppeteer очень полезен для автоматизированного тестирования.
  7. и т.д

В этом руководстве мы собираемся использовать Puppeteer для очистки веб-сайта со списком событий и создания ответа JSON с собранными данными.

Создание разборщика событий

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

Давайте начнем:

Создайте новый проект Node/Express

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

Создайте новый каталог проекта

mkdir NodeScrapper cd NodeScrapper

Выполните следующие команды, чтобы установить все зависимости:

npm i express puppeteer

Затем создайте файл index.js, который будет содержать нашу бизнес-логику.

touch index.js

Откройте файл index.js и вставьте следующий скрипт

const express = require('express')
const Events = require('./eventScript')
const app = express()
const port = 9000
app.get('/events', async (req, res) => {
   const events = await Events.getEvents()
   res.json(events)
})
app.listen(port, () => {})

Далее мы создадим файл eventScript.js и вставим в него следующий скрипт.

touch eventScript.js

Создание класса событий

Во-первых, мы импортируем puppeteer и определим URL-адрес, который мы хотим очистить.

const puppeteer = require('puppeteer')
const eventUrl = `https://www.meetup.com/find/keywords=backend&dateRange=this-week`
let page
let browser
let cardArr = []
class Events {
   // Lot of codes in here
}

Создание метода Init

Далее мы создадим метод init, который инициализирует наш кукольник с некоторой полезной конфигурацией.

В методе init происходит следующее: мы запускаем puppeteer и создаем новую страницу с объектом браузера.

Затем мы используем объект страницы для посещения определенного URL-адреса и waitForSelector для загрузки определенного селектора CSS, который мы хотим очистить.

Поэтому перед этим вам нужно будет перейти на веб-сайт и страницу, которую вы хотите очистить, и открыть инструмент Inspector вашего Google DevTool, чтобы увидеть конкретный селектор или тег, в котором содержится контент, который вы хотите очистить.

В этой демонстрации я просто захожу по указанному выше URL-адресу и проверяю страницу.

Глядя на изображение выше, мы замечаем, что селектор, содержащий все события, которые мы хотим очистить, — это .css-j7qwjs, это то, что мы решили дождаться загрузки с page.waitForSelector.

static async init() {
// console.log('Loading Page ...')
browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--single-process', // <- this one doesn't works in Windows
'--disable-gpu',
],
})
 page = await browser.newPage()
 await Promise.race([
    await page.goto(eventUrl, { waitUntil: 'networkidle2' }).catch(() => {}),
    await page.waitForSelector('.css-j7qwjs').catch(() => {}),
 ])
}

Некоторые конфигурации внутри массива args просто помогают похвастаться производительностью и рекомендуются Heroku, если вы используете их для развертывания.

Создание метода разрешения

Далее мы создадим метод resolve, который вызовет метод init и оценит страницу с помощью метода page.evaluate.

static async resolve() {
await this.init()
const eventURLs = await page.evaluate(() => {
   const cards = document.querySelectorAll('.css-1gl3lql')
   cardArr = Array.from(cards)
   const cardLinks = []
   cardArr.map((card) => {
      const eventLink = card.querySelector('.css-2ne5m0')
      const eventTitle = card.querySelector('.css-1jy1jkx')
      const eventGroupName = card.querySelector('.css-ycqk9')
      const eventImage = card.querySelector('img')
      const eventDate = card.querySelector('.css-ai9mht')
      const { host } = eventLink
      const { protocol } = eventLink
      const pathName = eventLink.pathname
      const query = eventLink.search
      const eventURL = protocol + '//' + host + pathName + query
      const eventGroup = eventGroupName !== null ? eventGroupName.textContent.split('Group name:')[1] : eventGroupName
    cardLinks.push({
      eventText: eventTitle !== null ? eventTitle.textContent : eventTitle,
      eventURLHost: host,
      eventURL: eventURL,
      eventGroup: eventGroup,
      eventImage: eventImage.src,
      date: eventDate !== null ? eventDate.textContent : eventDate,
    })
 })
return cardLinks
})
return eventURLs
}

Когда вы вызываете page.evaluate на веб-странице с Puppeteer, это дает вам гибкость в управлении DOM этой страницы с помощью ваших обычных функций DOM.

В нашем случае мы использовали document.querySelectorAll(), чтобы выбрать все узлы, которые имеют этот конкретный класс, который мы хотим очистить.

Если вы снова посмотрите на проверку страницы событий, вы увидите, что каждое из событий имеет этот класс css-1gl3lql в корневом родительском элементе.

Итак, собрав все события с помощью document.querySelectorAll(), мы проходим по каждому из них и отображаем нужные нам данные в массив cardLinks и возвращаем данные очистки.

Создание метода GetEvents

Наконец, мы создаем методы getEvents и вызываем в них метод разрешения.

static async getEvents() { 
   const events = await this.resolve() 
   await browser.close() return events 
}

После получения событий мы закрываем объект browser и возвращаем события.

Давайте соберем все вместе для более четкого представления.

const puppeteer = require('puppeteer')
const eventUrl = `https://www.meetup.com/find/?keywords=backend`
let page
let browser
let cardArr = []
class Events {
static async init() {
   // console.log('Loading Page ...')
   browser = await puppeteer.launch({
 args: [
   '--no-sandbox',
   '--disable-setuid-sandbox',
   '--disable-dev-shm-usage',
   '--disable-accelerated-2d-canvas',
   '--no-first-run',
   '--no-zygote',
   '--single-process', // <- this one doesn't works in Windows
   '--disable-gpu',
 ],
})
page = await browser.newPage()
 await Promise.race([
   await page.goto(eventUrl, { waitUntil: 'networkidle2' }).catch(() => {}),
   await page.waitForSelector('.css-j7qwjs').catch(() => {}),
 ])
}
static async resolve() {
   await this.init()
   const eventURLs = await page.evaluate(() => {
     const cards = document.querySelectorAll('.css-1gl3lql')
     cardArr = Array.from(cards)
     const cardLinks = []
     cardArr.map((card) => {
      const eventLink = card.querySelector('.css-2ne5m0')
      const eventTitle = card.querySelector('.css-1jy1jkx')
      const eventGroupName = card.querySelector('.css-ycqk9')
      const eventImage = card.querySelector('img')
      const eventDate = card.querySelector('.css-ai9mht')
      const { host } = eventLink
      const { protocol } = eventLink
      const pathName = eventLink.pathname
      const query = eventLink.search
      const eventURL = protocol + '//' + host + pathName + query
      const eventGroup = eventGroupName !== null  ? eventGroupName.textContent.split('Group name:')[1] : eventGroupName
      cardLinks.push({
        eventText: eventTitle !== null ? eventTitle.textContent : eventTitle,
        eventURLHost: host,
        eventURL: eventURL,
        eventGroup: eventGroup,
        eventImage: eventImage.src,
        date: eventDate !== null ? eventDate.textContent : eventDate,
    })
  })
 return cardLinks
})
return eventURLs
}
static async getEvents() {
   const events = await this.resolve()
   await browser.close()
   return events
 }
}
export default Events

Тестируя наш недавно разработанный продукт, выполните следующую команду, а затем перейдите по URL-адресу.

N/B: имена классов могут измениться для веб-страницы, когда вы читаете это, поэтому всегда используйте Google DevTools для проверки правильных имен селекторов.

node index.js 
// Then visit 
http://localhost:9000

Если вы все настроили правильно, вас должен приветствовать ответ JSON, содержащий ваши события.

Отдохните и подпишитесь, чтобы получать ежедневные статьи о разработке серверной части Nodejs, которые повысят вашу продуктивность.

Является ли веб-скрейпинг незаконным?

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

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

Нарушение авторского права.

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

Что ж, некоторые данные, которые мы можем очистить, защищены авторским правом, поэтому вы можете посетить документ об авторских правах на этом веб-сайте, чтобы узнать, что разрешено, а что нет.

Робот.txt

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

Использование API

Используйте API, если он предоставляется, вместо извлечения данных из Интернета.

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

Условия предоставления услуг

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

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

Очистка общедоступного контента

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

Отладка с помощью Puppeteer

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

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

Создание скриншотов

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

Чтобы делать скриншоты с помощью puppeteer, вам нужно добавить следующий код в ваши скрипты выше.

await page.screenshot({ path: 'screenshot.png' });

screenshot.png — это имя снимка экрана, также можно указать полный путь, куда будет сохранен снимок экрана.

Полезные ресурсы

Вывод

Мы подробно обсудили полное руководство по парсингу веб-страниц с помощью Nodejs и puppeteer.

Мы обсудили, почему вы должны парсить веб-страницы, важность и варианты его использования, мы также обсудили юридические аспекты парсинга веб-страниц и как начать парсинг веб-страниц с помощью Nodejs и puppeteer.

Первоначально опубликовано на https://masteringbackend.com 12 декабря 2020 г.