Google Scholar, это место, куда идут исследователи, студенты и учёные для поиска научных статей, материалов конференций, диссертаций и цитат практически по любой дисциплине. Страница результатов представляет собой компактную библиографическую запись: каждое объявление содержит название работы, авторов, место и время публикации, количество цитирований и ссылку на источник. Это делает Google Scholar полезной отправной точкой для обзоров литературы, анализа цитирований и отслеживания эволюции темы во времени.
Это руководство показывает, как парсить результаты Google Scholar с помощью Python надёжным способом. Вы создадите небольшой работоспособный скрапер, который получает отрисованную страницу результатов через Crawling API, парсит каждый результат с помощью BeautifulSoup и экспортирует чистые записи в JSON и CSV. Всё руководство ограничено публичными библиографическими данными, которые любой может видеть на странице результатов, а раздел о правовых вопросах ближе к концу, не просто формальность, поэтому прочитайте его, прежде чем направить скрапер на реальные объёмы данных.
Что вы создадите
Скрипт на Python, который принимает URL поиска Google Scholar, получает HTML через Crawling API и извлекает структурированную запись для каждого результата на странице. В качестве рабочего примера мы будем использовать запрос "Data Science" и извлекать следующие поля из каждого результата:
- Название, название статьи или книги, как показано в объявлении.
- Авторы, имена авторов, разобранные из строки под заголовком.
- Публикация, журнал, конференция, издатель или источник, указанный в строке авторов.
- Год, год публикации, если строка авторов его включает.
- Цитирования, количество цитирований из ссылки "Cited by" под результатом.
- Ссылка, URL назначения, на который указывает заголовок результата.
Почему обычный запрос не работает на Google Scholar
Если отправить обычный HTTP-запрос к URL результатов Google Scholar из скрипта, вы редко получите чистую страницу, которую видите в браузере. Scholar внимательно следит за автоматическим трафиком. Запросы, не похожие на запросы реального браузера, получают CAPTCHA, проверочную страницу или ограничение скорости после нескольких вызовов, а один IP-адрес дата-центра с повторяющимися запросами сразу выдаёт себя. Страница также в некоторых местах использует скриптинг, поэтому статические запросы могут возвращать неполный контент, который показал бы браузер с отрисовкой.
Поэтому рабочий скрапер Scholar требует двух вещей в одном запросе: IP-адреса, который платформа воспринимает как реального посетителя, и браузера, который при необходимости отрисовывает страницу. Можно собрать это самостоятельно с помощью безголового браузера плюс пула ротирующихся резидентных прокси, но поддержание их в рабочем состоянии, это большая часть всей работы. Crawling API объединяет обе вещи в одном вызове: вы отправляете URL, API получает данные с доверенного резидентного IP, отрисовывает при необходимости и возвращает готовый HTML для парсинга.
Google Scholar, одна из самых быстрых целей для получения CAPTCHA при обнаружении серии автоматических запросов с одного адреса. Crawling API ротирует резидентные IP и поглощает эти вызовы на стороне сервера, поэтому вам не нужно самостоятельно искать прокси или решать CAPTCHA. Вы можете начать с 1 000 бесплатных запросов без кредитной карты.
Предварительные требования
Перед написанием кода нужно подготовить несколько вещей. Ни одна из них не займёт много времени.
Базовые знания Python. Вы должны уверенно писать и запускать Python-скрипты и устанавливать пакеты через pip. Если BeautifulSoup вам незнаком, наше руководство по использованию BeautifulSoup в Python охватывает основы парсинга, которые предполагает этот учебник.
Python 3.8 или новее. Проверьте версию командой python --version. Если Python не установлен, скачайте его с python.org или через дистрибутив вроде Anaconda.
Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте токен запроса. Crawlbase предлагает два типа токенов: Normal и JavaScript; для Google Scholar подходит Normal-токен. Первые 1 000 запросов бесплатны. Храните токен как пароль: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.
Настройка проекта
Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, затем установите две библиотеки, необходимые скраперу.
python --version python -m venv scholar_env source scholar_env/bin/activate pip install requests beautifulsoup4
В Windows активируйте окружение командой scholar_env\Scripts\activate вместо строки с source. Два пакета выполняют основную работу: requests отправляет HTTP-вызов к Crawling API, а beautifulsoup4 парсит возвращаемый HTML, чтобы вы могли извлекать отдельные поля по CSS-селектору.
Шаг 1: Получение страницы через Crawling API
Начните с получения HTML. Напишите небольшую функцию crawl(), которая отправляет целевой URL в Crawling API с вашим токеном, проверяет, что базовая страница Scholar вернулась со статусом 200, и возвращает тело HTML. Проверка статуса перед парсингом позволяет сразу замечать ошибки, а не замалчивать их.
import json import requests API_TOKEN = "YOUR_CRAWLBASE_TOKEN" # replace with your token API_ENDPOINT = "https://api.crawlbase.com/" def crawl(url): params = {"token": API_TOKEN, "url": url} response = requests.get(API_ENDPOINT, params=params) response.raise_for_status() data = json.loads(response.text) if data["original_status"] != 200: raise Exception(f"Unable to crawl '{url}'") return data["body"] if __name__ == "__main__": url = "https://scholar.google.com/scholar?q=Data+Science" html = crawl(url) print(html[:500])
API возвращает JSON-конверт, поэтому вы загружаете ответ через json.loads и читаете два поля: original_status, статус, который вернул сам Google Scholar, а body, HTML страницы. Проверка original_status означает, что страница CAPTCHA или блок всплывают как исключение, а не передают мусор в парсер. Поисковый запрос передаётся в параметре q, именно так Scholar переносит запрос. Запустите скрипт командой python crawling.py, и вы должны увидеть реальную разметку результатов в первых 500 символах, что подтверждает работоспособность получения данных до написания первого селектора.
Проверка original_status всегда возвращает 200 именно потому, что запрос достиг Google Scholar как реальный посетитель с самого начала. Crawling API получает страницу с ротирующегося резидентного IP, поглощает CAPTCHA-вызовы Scholar для автоматического трафика и отрисовывает при необходимости, затем возвращает готовый HTML. Вам не нужно самостоятельно управлять безголовым парком и искать пул резидентных прокси. Начните с публичного URL результатов на бесплатном тарифе.
Шаг 2: Изучение структуры результатов
Перед парсингом откройте страницу результатов Google Scholar в браузере, щёлкните правой кнопкой по результату и выберите «Просмотр кода», чтобы увидеть структуру каждого объявления. Каждый результат завёрнут в элемент div.gs_r с атрибутом data-rp, содержащим его позицию. Внутри этой обёртки заголовок находится в заголовочном элементе h3.gs_rt со ссылкой назначения в виде анкора внутри него, строка авторов (авторы, публикация, год), в элементе div.gs_a, фрагмент находится в div.gs_rs, а счётчик цитирований "Cited by" отображается в ссылках футера под div.gs_fl. Эти имена классов и являются селекторами для парсера.
Одно поле требует небольшой обработки, строка авторов. Google Scholar упаковывает авторов, публикацию и год в одну строку gs_a, разделённую дефисами, например: H Wickham, M Çetinkaya-Rundel - 2023 - books.google.com. Мы разобьём эту строку, чтобы извлечь три части на следующем шаге.
Шаг 3: Парсинг результатов с помощью BeautifulSoup
Имея HTML на руках, загрузите его в BeautifulSoup и извлеките каждый результат по селекторам из предыдущего шага. Парсер строки авторов разбивает текст gs_a по разделителям-дефисам, а затем сканирует средний и конечный сегменты в поисках четырёхзначного года, чтобы авторы, публикация и год попали в отдельные поля.
import re from bs4 import BeautifulSoup def parse_byline(text): # gs_a packs "authors - publication, year - host" parts = [p.strip() for p in text.split(" - ")] authors = parts[0] if parts else "" publication = parts[1] if len(parts) > 1 else "" year = None match = re.search(r"\b(19|20)\d{2}\b", text) if match: year = match.group() publication = re.sub(r",?\s*" + year, "", publication).strip() return authors, publication, year def parse_citations(result_item): for a in result_item.select("div.gs_fl a"): text = a.get_text(strip=True) if text.startswith("Cited by"): return int(text.replace("Cited by", "").strip()) return 0 def parse_google_scholar(html): soup = BeautifulSoup(html, "html.parser") results = [] for item in soup.select("div.gs_r[data-rp]"): heading = item.find("h3", class_="gs_rt") link = item.select_one("h3.gs_rt > a") byline = item.find("div", class_="gs_a") if not heading: continue authors, publication, year = "", "", None if byline: authors, publication, year = parse_byline(byline.get_text(strip=True)) results.append({ "position": int(item["data-rp"]), "title": heading.get_text(strip=True), "authors": authors, "publication": publication, "year": year, "citations": parse_citations(item), "link": link["href"] if link else None, }) return results
Селектор div.gs_r[data-rp] соответствует каждой обёртке результата и пропускает блоки вёрстки без позиции. Для каждой обёртки h3.gs_rt даёт заголовок, а анкор внутри него, ссылку, div.gs_a передаётся парсеру строки авторов, а parse_citations перебирает ссылки футера в div.gs_fl в поисках записи "Cited by", возвращая 0, если у статьи нет цитирований. Считывание позиции непосредственно из data-rp соответствует рангу, который Scholar сам присваивает. Защита if not heading: continue исключает посторонние элементы разметки из вывода.
Google периодически изменяет разметку Scholar. Такие имена классов, как gs_rt, gs_a и gs_fl, долгое время были стабильными, но рассматривайте их как начальный шаблон, а не контракт. Если поле возвращается пустым для каждого результата, проверьте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание селекторов, норма для любого производственного скрапера.
Шаг 4: Объединение и экспорт в JSON и CSV
Теперь свяжите получение и парсинг в один работоспособный скрипт, а затем запишите структурированный вывод в JSON и CSV. JSON сохраняет вложенную структуру для программного использования, а CSV сразу открывается в таблице или фрейме данных pandas для обзора литературы. Установка ensure_ascii=False сохраняет читаемость имён авторов с символами с диакритическими знаками.
import csv import json import requests from bs4 import BeautifulSoup from scholar_parser import parse_google_scholar # the parser from step 3 API_TOKEN = "YOUR_CRAWLBASE_TOKEN" API_ENDPOINT = "https://api.crawlbase.com/" FIELDS = ["position", "title", "authors", "publication", "year", "citations", "link"] def crawl(url): params = {"token": API_TOKEN, "url": url} response = requests.get(API_ENDPOINT, params=params) response.raise_for_status() data = json.loads(response.text) if data["original_status"] != 200: raise Exception(f"Unable to crawl '{url}'") return data["body"] def save_json(results, path="scholar_results.json"): with open(path, "w", encoding="utf-8") as f: json.dump(results, f, ensure_ascii=False, indent=2) def save_csv(results, path="scholar_results.csv"): with open(path, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=FIELDS) writer.writeheader() writer.writerows(results) def main(): query = "Data Science" url = f"https://scholar.google.com/scholar?q={query.replace(' ', '+')}" html = crawl(url) results = parse_google_scholar(html) save_json(results) save_csv(results) print(f"Saved {len(results)} results to JSON and CSV") if __name__ == "__main__": main()
Запустите полный скрипт командой python main.py. Он получает страницу результатов для "Data Science", извлекает запись для каждого объявления и записывает scholar_results.json и scholar_results.csv. Тех же двух функций достаточно: замените запрос, и парсер обработает всё, что вернётся.
Как выглядит вывод
Вы получаете упорядоченный список объектов результатов, каждый с разобранным заголовком, авторами, публикацией, годом, количеством цитирований и ссылкой, готовых для записи в JSON, CSV или базу данных.
[ { "position": 0, "title": "[BOOK][B] R for data science", "authors": "H Wickham, M Çetinkaya-Rundel, G Grolemund", "publication": "books.google.com", "year": "2023", "citations": 8421, "link": "https://books.google.com/books?id=TiLEEAAAQBAJ" }, { "position": 1, "title": "Data science and its relationship to big data and data-driven decision making", "authors": "F Provost, T Fawcett", "publication": "Big data", "year": "2013", "citations": 2510, "link": "https://www.liebertpub.com/doi/abs/10.1089/big.2013.1508" } ]
Зеркало CSV содержит те же столбцы, по одной строке на результат, с заголовком position,title,authors,publication,year,citations,link. Этот формат нужен большинству рабочих процессов обзора литературы, поскольку вы можете сортировать по количеству цитирований или фильтровать по году прямо в таблице.
Обработка пагинации
Один запрос на одной странице, это демонстрация; реальная задача требует более глубокого погружения в результаты. Google Scholar пагинирует с помощью параметра запроса start, который является смещением кратным 10: start=10, вторая страница, start=20, третья, и так далее, по десять результатов на странице. Форма остаётся той же: сформируйте каждый URL страницы, получите его через Crawling API и спарсите той же функцией. Дозируйте запуск с паузой между запросами, а не запускайте их в плотном цикле.
import time def fetch_paginated_results(base_url, max_pages=5): all_results = [] for page in range(max_pages): start = page * 10 # 10 results per page url = f"{base_url}&start={start}" html = crawl(url) all_results.extend(parse_google_scholar(html)) time.sleep(3) return all_results base_url = "https://scholar.google.com/scholar?q=Data+Science" results = fetch_paginated_results(base_url, max_pages=5) print(f"Collected {len(results)} results across 5 pages")
Любой ответ 5XX от Crawling API бесплатен, поэтому повтор заблокированного или недоступного URL ничего не стоит. Если вы предпочитаете маршрутизировать собственный трафик через ротирующийся пул, а не использовать управляемый API, Smart AI Proxy предоставляет ту же ротацию резидентных IP в виде прокси-эндпоинта. Для хранения результатов более одного запуска записывайте записи каждой страницы в базу данных, например SQLite, по мере поступления, с ключом по заголовку и ссылке, а не держите всё в памяти.
Поддержание разблокированного состояния
Даже при обработанном доверенном IP Google Scholar следит за трафиком с признаками скрапинга и прибегает к CAPTCHA быстрее, чем большинство поисковых целей. Несколько привычек помогут поддерживать запуск в рабочем состоянии.
- Дозируйте запросы. Атака страниц результатов в плотном цикле, самый быстрый способ получить проверку. Распределяйте запросы и варьируйте запросы, вместо того чтобы листать один запрос на полной скорости.
- Опирайтесь на ротацию. Пул резидентных IP распределяет запросы по множеству адресов реальных пользователей, чтобы ни один не превысил лимит. Crawling API делает это за вас; если вы создаёте собственный стек, именно эту часть нужно реализовать правильно.
- Читайте коды статусов. Запуск, который начинает возвращать страницы CAPTCHA или верификации, сигнализирует о том, что текущая скорость или IP-тир больше не достаточны. Воспринимайте это как сигнал к отступлению, а не как шум, который можно игнорировать.
- Проверяйте страницу при пустых полях. Scholar периодически меняет разметку. Если результаты перестали парситься, откройте живую страницу в инструментах разработчика и обновите селекторы.
Общее руководство по тактике см. в статье как парсить сайты без блокировок. Если вы также парсите основной индекс Google, наше руководство по парсингу страниц поиска Google охватывает обычную структуру SERP, а общее руководство по парсингу с Python разбирает основы, на которых строится этот учебник.
Законен ли скрапинг Google Scholar?
Допустимость скрапинга Google Scholar зависит от условий использования Google, вашей юрисдикции и того, как вы используете данные. Условия Google Scholar ограничивают автоматический доступ и прямо не поощряют скрапинг в коммерческих целях, поэтому автоматический сбор данных может противоречить этим условиям вне зависимости от тщательности вашего инструментария. Ни один из приведённых здесь кодов не меняет этого; он лишь решает техническую часть задачи. Прочитайте условия Scholar и его robots.txt и рассматривайте оба документа как границу того, что вы собираете.
Несколько правил, которых стоит придерживаться. Собирайте только публичные библиографические данные: заголовки, авторов, детали публикации, годы, количество цитирований и ссылки, которые любой может видеть на странице результатов без учётной записи. Поддерживайте достаточно низкий объём запросов, чтобы не нагружать серверы Scholar, и дозируйте сканирование, а не запускайте его на полную мощность. Важно: объявления, это метаданные о работах, а не сами работы. Не используйте скрапер для получения или распространения полного текста статей, находящихся за платным доступом или лицензией издателя; это отдельный вопрос, не связанный с чтением публичных метаданных цитирований, и он не рассматривается здесь.
Это руководство намеренно ограничено публичными страницами результатов, поскольку именно это позволяет сохранить правомерность работы. Google не публикует широкодоступный официальный API Scholar для такого рода доступа, поэтому нет санкционированного высокообъёмного эндпоинта, что ещё раз подчёркивает необходимость скромного масштаба и уважения к правилам сайта. Если ваш проект требует большего, чем публичные метаданные в малых объёмах, лицензированный библиографический датасет или официальный API издателя, правильный путь, а не более хитрый скрапер.
Ключевые выводы
- Scholar быстро блокирует трафик с признаками скрапинга. CAPTCHA появляются быстро при обнаружении автоматических запросов с одного IP, поэтому для получения реальных результатов нужен доверенный резидентный адрес.
- Crawling API получает данные через реальный IP. Отправьте URL, API ротирует резидентные IP и поглощает CAPTCHA на стороне сервера, затем возвращает готовый HTML для парсинга.
-
BeautifulSoup выполняет извлечение. Выберите каждый элемент
div.gs_r[data-rp], затем считайте заголовок, ссылку и строку авторовgs_a, и разбейте эту строку на авторов, публикацию и год. -
Цитирования и пагинация просты. Считайте количество цитирований "Cited by" из
div.gs_flи углубляйтесь с помощью смещенияstartкратным 10, делая паузу между страницами. - Оставайтесь в рамках публичных метаданных. Соблюдайте условия Scholar и robots.txt, поддерживайте низкий объём и никогда не получайте полный текст за платным доступом или личные данные.
Часто задаваемые вопросы
Почему обычный запрос не работает или возвращает CAPTCHA на Google Scholar?
Scholar помечает трафик, не похожий на запросы реального браузера, и быстро ограничивает повторяющиеся запросы с одного IP дата-центра, поэтому обычный скрипт обычно получает CAPTCHA или страницу верификации вместо результатов. Получение данных через Crawling API, использующий ротирующиеся резидентные IP и обрабатывающий CAPTCHA-вызовы на стороне сервера, делает запрос похожим на запрос обычного посетителя, и вы получаете реальную страницу результатов.
Как парсить данные Google Scholar с помощью Python?
Используйте библиотеку requests для отправки URL поиска в Crawling API, затем спарсите возвращаемый HTML с помощью BeautifulSoup. Выберите каждый результат div.gs_r[data-rp] и считайте заголовок из h3.gs_rt, строку авторов из div.gs_a и количество цитирований из div.gs_fl. Для основ парсинга см. наше руководство по BeautifulSoup.
Какие поля можно извлечь из результата Google Scholar?
В этом руководстве извлекается заголовок, авторы, публикация, год, количество цитирований и ссылка из каждого результата, плюс позиция из атрибута data-rp. Авторы, публикация и год все приходят из единой строки авторов gs_a, которую парсер разбирает. Оставайтесь в рамках публичных библиографических метаданных и не получайте полный текст за платным доступом.
Как получить количество цитирований для каждой работы?
Футер каждого результата, блок div.gs_fl, содержит ссылку "Cited by N", если у работы есть цитирования. Парсер просматривает эти ссылки, находит ту, что начинается с "Cited by", и считывает число с конца, возвращая 0 для работ без цитирований.
Как пагинировать через больше результатов Google Scholar?
Используйте параметр запроса start, который является смещением кратным 10: start=10, вторая страница, start=20, третья, и так далее, по десять результатов на странице. Сформируйте URL каждой страницы со смещением, получите его через Crawling API, спарсите той же функцией и делайте паузу несколько секунд между запросами, чтобы дозировать сканирование, а не перегружать систему.
Можно ли анализировать спарсенные данные Google Scholar впоследствии?
Да. Экспортируйте результаты в CSV или JSON, затем загрузите их в инструмент вроде pandas для анализа. Поскольку записи содержат количество цитирований и годы, можно сортировать по влиянию, фильтровать по актуальности или строить графики роста публикаций по теме со временем, что именно то, что нужно для обзора литературы.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
