Поиск всех авторов, исследователей в ResearchGate на Python

  • Что будет соскоблено
  • Предварительные условия
  • Полный код
  • Ссылки

Что будет соскоблено

Необходимые условия

Базовые знания о скраппинге с помощью селекторов CSS

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

Отдельная виртуальная среда

Если вы раньше не работали с виртуальным окружением, посмотрите специализированный учебник по виртуальным окружениям Python с использованием Virtualenv и статью из моего блога Poetry, чтобы ознакомиться с ними.

Снизить вероятность блокировки

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

📌Примечание: если вы будете использовать этот фрагмент кода без прокси, запросы будут блокироваться в течение короткого периода времени. Скраппинг с прокси большого объема данных — это выход.

Установите библиотеки:

pip install parsel playwright
Войдите в полноэкранный режим Выйти из полноэкранного режима

Полный код

from parsel import Selector
from playwright.sync_api import sync_playwright
import json


def scrape_researchgate_profile(query: str):
    with sync_playwright() as p:

        browser = p.chromium.launch(headless=True, slow_mo=50)
        page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36")

        authors = []
        page_num = 1

        while True:
            page.goto(f"https://www.researchgate.net/search/researcher?q={query}&page={page_num}")
            selector = Selector(text=page.content())

            for author in selector.css(".nova-legacy-c-card__body--spacing-inherit"):
                name = author.css(".nova-legacy-v-person-item__title a::text").get()
                thumbnail = author.css(".nova-legacy-v-person-item__image img::attr(src)").get()
                profile_page = f'https://www.researchgate.net/{author.css("a.nova-legacy-c-button::attr(href)").get()}'
                institution = author.css(".nova-legacy-v-person-item__stack-item:nth-child(3) span::text").get()
                department = author.css(".nova-legacy-v-person-item__stack-item:nth-child(4) span").xpath("normalize-space()").get()
                skills = author.css(".nova-legacy-v-person-item__stack-item:nth-child(5) span").xpath("normalize-space()").getall()
                last_publication = author.css(".nova-legacy-v-person-item__info-section-list-item .nova-legacy-e-link--theme-bare::text").get()
                last_publication_link = f'https://www.researchgate.net{author.css(".nova-legacy-v-person-item__info-section-list-item .nova-legacy-e-link--theme-bare::attr(href)").get()}'

                authors.append({
                    "name": name,
                    "profile_page": profile_page,
                    "institution": institution,
                    "department": department,
                    "thumbnail": thumbnail,
                    "last_publication": {
                        "title": last_publication,
                        "link": last_publication_link
                    },
                    "skills": skills,
                })

            print(f"Extracting Page: {page_num}")

            # checks if next page arrow key is greyed out `attr(rel)` (inactive) -> breaks out of the loop
            if selector.css(".nova-legacy-c-button-group__item:nth-child(9) a::attr(rel)").get():
                break
            else:
                # paginate to the next page
                page_num += 1


        print(json.dumps(authors, indent=2, ensure_ascii=False))

        browser.close()


scrape_researchgate_profile(query="coffee")
Войти в полноэкранный режим Выйти из полноэкранного режима

Объяснение кода

Импорт библиотек:

from parsel import Selector
from playwright.sync_api import sync_playwright
import json
Войти в полноэкранный режим Выйти из полноэкранного режима
Код Пояснение
parsel для разбора документов HTML/XML. Поддерживает XPath.
playwright для рендеринга страницы с помощью экземпляра браузера.
json преобразовать словарь Python в строку JSON.

Определить функцию и открыть playwright с помощью контекстного менеджера::

def scrape_researchgate_profile(query: str):
    with sync_playwright() as p:
        # ...
Войти в полноэкранный режим Выйти из полноэкранного режима
Код Объяснение
query: str сообщить Python, что query должен быть str.

Запустить экземпляр браузера, открыть new_page с переданным user-agent:

browser = p.chromium.launch(headless=True, slow_mo=50)
page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36")
Войти в полноэкранный режим Выйти из полноэкранного режима
Код Пояснение
p.chromium.launch() запустить экземпляр браузера Chromium.
headless явно указать playwright на запуск в безголовом режиме, даже если это значение является дефолтным.
slow_mo указать playwright на замедление выполнения.
browser.new_page() открыть новую страницу. user_agent используется для того, чтобы действовать как реальный пользователь, делающий запрос из браузера. Если он не используется, то по умолчанию будет установлено значение playwright, которое равно None. Проверьте, какой у вас user-agent.

Добавьте временный список, настройте цикл while и откройте новый URL:

authors = []

while True:
    page.goto(f"https://www.researchgate.net/search/researcher?q={query}&page={page_num}")
    selector = Selector(text=page.content())
    # ...
Вход в полноэкранный режим Выход из полноэкранного режима
Код Объяснение
goto() выполнить запрос к определенному URL с переданными параметрами запроса и страницы.
Selector() передать возвращаемые HTML-данные с помощью page.content() и обработать их.

Итерация над результатами автора на каждой странице, извлечение данных и append во временный list:

for author in selector.css(".nova-legacy-c-card__body--spacing-inherit"):
    name = author.css(".nova-legacy-v-person-item__title a::text").get()
    thumbnail = author.css(".nova-legacy-v-person-item__image img::attr(src)").get()
    profile_page = f'https://www.researchgate.net/{author.css("a.nova-legacy-c-button::attr(href)").get()}'
    institution = author.css(".nova-legacy-v-person-item__stack-item:nth-child(3) span::text").get()
    department = author.css(".nova-legacy-v-person-item__stack-item:nth-child(4) span").xpath("normalize-space()").get()
    skills = author.css(".nova-legacy-v-person-item__stack-item:nth-child(5) span").xpath("normalize-space()").getall()
    last_publication = author.css(".nova-legacy-v-person-item__info-section-list-item .nova-legacy-e-link--theme-bare::text").get()
    last_publication_link = f'https://www.researchgate.net{author.css(".nova-legacy-v-person-item__info-section-list-item .nova-legacy-e-link--theme-bare::attr(href)").get()}'

    authors.append({
        "name": name,
        "profile_page": profile_page,
        "institution": institution,
        "department": department,
        "thumbnail": thumbnail,
        "last_publication": {
            "title": last_publication,
            "link": last_publication_link
        },
        "skills": skills,
    })
Войти в полноэкранный режим Выйти из полноэкранного режима
Код Пояснение
css() для разбора данных из переданного селектора(ов) CSS. Каждый CSS-запрос траслируется в XPath с помощью пакета csselect под капотом.
извлечение текстовых или атрибутивных данных из узла.
для получения фактических данных из сопоставленного узла или для получения списка сопоставленных данных из узлов.
xpath("normalize-space()") для разбора пустого текстового узла. По умолчанию пустой текстовый узел пропускается XPath.

Проверять наличие следующей страницы и осуществлять постраничный переход:

# checks if the next page arrow key is greyed out `attr(rel)` (inactive) -> breaks out of the loop
if selector.css(".nova-legacy-c-button-group__item:nth-child(9) a::attr(rel)").get():
    break
else:
    page_num += 1
Войти в полноэкранный режим Выйти из полноэкранного режима

Распечатать извлеченные данные и закрыть экземпляр браузера:

print(json.dumps(authors, indent=2, ensure_ascii=False))

browser.close()

# call the function
scrape_researchgate_profile(query="coffee")
Войти в полноэкранный режим Выйти из полноэкранного режима

Часть вывода JSON:

[
  {
    "name": "Marina Ramón-Gonçalves", # first profile
    "profile_page": "https://www.researchgate.net/profile/Marina-Ramon-Goncalves?_sg=VbWMth8Ia1hDG-6tFnNUWm4c8t6xlBHy2Ac-2PdZeBK6CS3nym5PM5OeoSzha90f2B6hpuoyBMwm24U",
    "institution": "Centro Nacional de Investigaciones Metalúrgicas (CENIM)",
    "department": "Reciclado de materiales",
    "thumbnail": "https://i1.rgstatic.net/ii/profile.image/845010970898442-1578477723875_Q64/Marina-Ramon-Goncalves.jpg",
    "last_publication": {
      "title": "Extraction of polyphenols and synthesis of new activated carbon from spent coffe...",
      "link": "https://www.researchgate.netpublication/337577823_Extraction_of_polyphenols_and_synthesis_of_new_activated_carbon_from_spent_coffee_grounds?_sg=2y4OuZz32W46AWcUGmwYbW05QFj3zkS1QR_MVxvKwqJG-abFPLF6cIuaJAO_Mn5juJZWkfEgdBwnA5Q"
    },
    "skills": [
      "Polyphenols",
      "Coffee",
      "Extraction",
      "Antioxidant Activity",
      "Chromatography"
    ]
  }, ... other profiles
  {
    "name": "Kingsten Okka", # last profile
    "profile_page": "https://www.researchgate.net/profile/Kingsten-Okka?_sg=l1w_rzLrAUCRFtoo3Nh2-ZDAaG2t0NX5IHiSV5TF2eOsDdlP8oSuHnGglAm5tU6OFME9wgfyAd-Rnhs",
    "institution": "University of Southern Queensland ",
    "department": "School of Agricultural, Computational and Environmental Sciences",
    "thumbnail": "https://i1.rgstatic.net/ii/profile.image/584138105032704-1516280785714_Q64/Kingsten-Okka.jpg",
    "last_publication": {
      "title": null,
      "link": "https://www.researchgate.netNone"
    },
    "skills": [
      "Agricultural Entomology",
      "Coffee"
    ]
  }
]
Войти в полноэкранный режим Выйти из полноэкранного режима

Ссылки

  • GitHub Gist

Присоединяйтесь к нам в Twitter | YouTube

Добавить запрос на улучшение💫 или ошибку🐞

Оцените статью
Procodings.ru
Добавить комментарий