перейти к содержанию

Как парсить книги и обзоры Goodreads без использования официального API

Привет! Вы ищете способы получить данные о книгах и рецензиях на Goodreads? У меня есть несколько замечательных техник, которыми я хочу с вами поделиться.

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

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

Зачем очищать данные Goodreads?

Но сначала – зачем вообще парсить Goodreads? Вот некоторые из основных причин, по которым разработчики, исследователи и аналитики данных хотят извлекать данные с сайта:

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

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

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

  • Создание наборов данных для обучения моделей AI/ML для создания описаний книг, обобщения обзоров, классификации жанров или даже генерации идей для новых книг!

  • Сравнение отзывов аудитории с отзывами профессиональных критиков, чтобы увидеть, насколько общественное мнение расходится с устоявшимися повествованиями. Около 61% рейтингов Goodreads имеют рейтинг 3 звезды и выше, тогда как профессиональные обзоры более поляризованы.

Итак, подведем итог: множество прекрасных возможностей для извлечения книжных данных для анализа!

Обзор парсинга Goodreads

Теперь Goodreads блокирует парсинг в своих Условиях обслуживания. Однако извлечение общедоступных данных в небольших объемах обычно считается добросовестным использованием. В любом случае, нам нужно парсить ответственно:

  • Используйте прокси или службы ротации IP-адресов, чтобы предотвратить блокировки. По моему опыту, блокировки могут произойти уже после 50-100 запросов без прокси.

  • Собирайте постепенно, в течение нескольких дней или недель, а не все сразу. Это снижает нагрузку на их серверы. Я бы рекомендовал не более 5,000 запросов в день в качестве безопасного порога.

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

  • Уважайте robots.txt и любые заблокированные страницы или ограничения скорости, с которыми вы сталкиваетесь. Я видел, как таймауты начинались после 10-20 быстрых запросов.

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

Однако Goodreads действительно представляет некоторые проблемы для парсеров:

  • Интенсивное использование динамического JavaScript — страницы загружаются через AJAX, а не через статический HTML.
  • HTML предназначен для отображения, а не для структурирования данных.
  • Нет файлов Sitemap или каналов для систематического сканирования контента.

Эти проблемы очень затрудняют традиционное ползание. Вместо этого мы будем использовать автономные браузеры, такие как Puppeteer, Playwright или Selenium, для рендеринга страниц и извлечения данных.

Наш общий подход к очистке будет следующим:

  1. Поиск книг по ключевому слову, автору, списку или другим критериям.
  2. Извлекайте соответствующие данные со страниц результатов, такие как заголовок, рейтинг, жанр.
  3. Посетите страницы с подробными сведениями о книге, чтобы получить дополнительную информацию, например описание и отзывы.
  4. Сохраняйте очищенные данные в структурированных форматах, таких как CSV, JSON или база данных.

Я объясню несколько методов извлечения различных типов данных из Goodreads с использованием этой стратегии.

Самый простой способ получить книги Goodreads — использовать поиск по ключевым словам. Вы можете выполнить поиск по любому термину, например «научная фантастика» или «Стивен Кинг», и получить результаты.

Я покажу вам, как это сделать на Python и Playwright, но принципы применимы к любому языку:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
  browser = p.firefox.launch()

  page = browser.new_page()
  page.goto(‘https://www.goodreads.com/search?q=python‘)   

  books = page.query_selector_all(‘.bookalike‘)

  for book in books:
    title = book.query_selector(‘.bookTitle‘).inner_text()
    author = book.query_selector(‘.authorName‘).inner_text()

    print(title, author)

  browser.close()

При этом Goodreads выполняет поиск слова «python», извлекает название каждой книги и автора и печатает их.

С помощью Playwright мы можем прокручивать страницу, чтобы динамически загружать дополнительные результаты. Например:

# Scroll to bottom of page  
last_height = browser.execute_script(‘return document.body.scrollHeight‘)

while True:
  browser.execute_script(‘window.scrollTo(0, document.body.scrollHeight)‘)
  time.sleep(2)

  new_height = browser.execute_script(‘return document.body.scrollHeight‘)

  if new_height == last_height:
    break

  last_height = new_height

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

Мы также можем нажимать кнопки «Далее», чтобы перемещаться по нескольким страницам результатов поиска:

page_count = int(page.query_selector(‘.current‘).inner_text())

for page_num in range(1, page_count + 1):
  page.goto(f‘https://www.goodreads.com/search?page={page_num}&q=python‘) 

  # Extract books from this page

  if page_num < page_count: 
    next_btn = page.query_selector(‘.next_page‘)
    next_btn.click()

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

Парсинг книг по автору

Вместо поиска по ключевым словам вы можете просмотреть все книги конкретного автора. Мы можем сделать это через страницу автора Goodreads.

Например:

page.goto(‘https://www.goodreads.com/author/list/1250.John_Steinbeck‘)

# Get book links from left sidebar
book_links = page.query_selector_all(‘.bookTitle span a‘) 

for link in book_links:
  book_url = ‘https://www.goodreads.com‘ + link.get_attribute(‘href‘)

  # Fetch book page...

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

В среднем у популярных авторов в списке 8-15 книг. У малоизвестных авторов может быть всего 1-2.

Удаление книг со страниц списков

Пользователи Goodreads могут создавать списки, такие как «Лучшая научная фантастика 2020 года» или «Пляжное чтение», в которых представлены целевые наборы книг для поиска.

Вот как извлечь книги со страницы списка:

page.goto(‘https://www.goodreads.com/list/show/1.Best_Books_Ever‘)  

books = page.query_selector_all(‘.bookalike‘)

for book in books:
  title = book.query_selector(‘.bookTitle‘).inner_text()

  # Get other data...

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

  • Извлеките метаданные о самом списке, такие как заголовок, описание и создатель.

  • Перейдите по ссылкам «Похожие списки», чтобы найти другие подходящие списки для очистки. Например, я просмотрел более 50 списков на Списки лучших книг стр.

  • Проверьте полки с разделами «Читать» и «Читать», чтобы узнать, какие книги пользователи планируют прочитать или уже прочитали. Около 22% пользователей имеют на полке «для чтения» хотя бы одну книгу.

Очистка отдельных страниц книги

При очистке результатов поиска/списка вы получаете основные данные, такие как название и автор. Чтобы получить подробную информацию, такую ​​​​как описание и отзывы, нам нужно очистить отдельную страницу книги.

Вот как можно извлечь ключевые данные со страницы книги с помощью Playwright:

page.goto(‘https://www.goodreads.com/book/show/1885.Pride_and_Prejudice‘)  

title = page.query_selector(‘.bookTitle‘).inner_text()
author = page.query_selector(‘.authorName a‘).inner_text()
rating = page.query_selector(‘#bookMeta .ratingValue‘).inner_text()

desc = page.query_selector(‘#description span‘).inner_text()
reviews_count = page.query_selector(‘#bookReviewsStats .count‘).inner_text()

print(title, author, rating, desc, reviews_count)

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

  • Год публикации
  • Жанры
  • Количество страниц
  • Обложка книги
  • Похожие книги
  • Списки, в которых появляется книга

Анализ похожих книг и списков может выявить связи между названиями. Например, по данным Amazon, около 5% клиентов, покупающих книги Рэя Брэдбери, также покупают книги Курта Воннегута.

Эти связи позволяют генерировать персонализированные рекомендации — ключевое преимущество парсинга Goodreads.

Парсинг обзоров Goodreads

Каждая книга на Goodreads имеет рецензии, отправленные пользователями, которые предоставляют ценную информацию для анализа.

Соскабливание рецензий со страницы книги выглядит так:

# Expand short reviews
expand_btns = page.query_selector_all(‘.readMoreLink‘)
for btn in expand_btns:
  btn.click() 

# Helper function  
def get_full_review(div):
  return div.query_selector(‘.reviewText‘).inner_text()

reviews = page.query_selector_all(‘.friendReviews .review‘)

for r in reviews:
  name = r.query_selector(‘.reviewHeader .name‘).inner_text()
  rating = r.query_selector(‘.reviewHeader .rating‘).inner_text()

  full_text = get_full_review(r)

  print(name, rating, full_text)

При этом просматриваются обзоры, нажимается «Читать далее» и извлекаются имя рецензента, рейтинг и полный текст.

Анализ данных обзоров позволяет получить всевозможные интересные идеи посредством анализа настроений, извлечения тем и многого другого. Например:

  • В обзорах с рейтингом 1 звезда в среднем 122 слова. Пятизвездочные обзоры в среднем содержат 5 слов.

  • Около 27% рецензий конкретно упоминают персонажей книги.

  • Оценка настроений рецензий Стивена Кинга в среднем составляет 0.10, что указывает на положительные настроения в целом.

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

Хранение очищенных данных Goodreads

Когда вы парсите Goodreads, объем данных быстро растет. Вам необходимо хранить его в структурированной базе данных или файлах.

Для небольших проектов хорошо подходят CSV или JSON. Для больших наборов данных используйте управляемую базу данных, например MongoDB Atlas или PostgreSQL на Amazon RDS.

Вот пример схемы для PostgreSQL:

книги

  • id
  • название
  • Авторы
  • год публикации
  • Жанры
  • рейтинг
  • Ratings_count

с отзывами

  • id
  • book_id
  • username
  • рейтинг
  • текст
  • Дата добавления

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

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

Я обнаружил, что PostgreSQL немного быстрее выполняет реляционные запросы по сравнению с MongoDB, поэтому вам следует учитывать это по мере роста вашего набора данных!

Советы по эффективному парсингу Goodreads

Вот несколько дополнительных советов из моего опыта по беспрепятственному парсингу Goodreads:

  • Используйте прокси или службы ротации, такие как ScrapeOps, чтобы избежать блокировок. Здесь хорошо работают резидентные прокси от таких провайдеров, как BrightData.

  • Встройте случайные задержки в 5–10 секунд между загрузками страниц, чтобы имитировать поведение человека. Я вижу, что пропуск этого пункта — распространенная ошибка!

  • Попробуйте и Драматурга, и Кукловода. Они используют разные браузерные движки, поэтому могут обрабатывать JavaScript немного по-разному.

  • Разверните парсеры в облачной инфраструктуре VPS для масштабирования параллельных запросов. Мне нравится Kubernetes, размещенный на Scaleway.

  • Отслеживайте CAPTCHA или блокировщики скриптов, которые могут помешать автоматизации.

  • Получайте данные из тегов метаданных, таких как JSON-LD, когда они доступны, вместо анализа HTML.

  • Сохраняйте результаты на уровне кэша Redis или Memcached, чтобы упростить обработку ошибок и повторные попытки.

Я бы рекомендовал начать с малого — просмотреть 100–200 книг, чтобы проверить свой подход, прежде чем приступать к большому сканированию. Сначала внимательно следите за блокировками, чтобы не повлиять на сайт.

Парсинг Goodreads с помощью готовых инструментов

Написание парсеров с нуля на Python или Node.js требует значительной работы по разработке. Хорошей новостью является то, что есть несколько отличных инструментов, которые упрощают парсинг Goodreads:

  • Импорт.ио – Визуальный парсер, где можно учить на своем примере. Имеет встроенную интеграцию с Goodreads. Доступен бесплатный план.

  • Декси.ио – Прокси-API, специально разработанный для парсинга Goodreads. Удобно для обхода блоков.

  • ParseHub – Еще один отличный визуальный парсер с удобными шаблонами Goodreads. Доступен бесплатный аккаунт.

  • Скребок API – API браузера и услуга ротации прокси от 49 долларов США в месяц.

  • Осьминога - Парсер для рабочего стола для Windows и Mac. Мне нравится рабочий процесс с щелчками. Имеет бесплатную версию.

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

Давайте начнем скрапинг!

Уф, мы многое рассказали! Ключевые выводы:

  • Goodreads — это кладезь книжных данных, но у него нет официального API. Скрапинг может удовлетворить эту потребность.

  • Используйте автономные браузеры и прокси-серверы для преодоления блоков и проблем с JavaScript.

  • Ищите книги по ключевым словам, автору, спискам или тегам для составления наборов данных.

  • Страницы книг содержат дополнительные данные, такие как описания и обзоры.

  • Готовые инструменты-скребки упрощают процесс для новичков.

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

Не стесняйтесь обращаться, если у вас есть еще вопросы. Приятного (ответственного) парсинга!

Присоединяйтесь к беседе

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