Парсинг исторических данных с Google Scholar используя Python

Kate

Administrator
Команда форума

Что парсим​

Из органических результатов:

c19ed25b0b51971cfe0ddc1204110a66.png

📌Примечание: На Google Scholar есть максимальный лимит в 100 страниц, поэтому когда вы видите About xxx.xxx results это не означает что все результаты отображаются и их можно спарсить. Так же как это происходит с Гугл поиском.

Из цитируемых результатов:

5a506c0f6c215cde4f7716cc7c1165eb.png

Что понадобится​

Отдельное вирутуальное окружение

Если вы не работали с виртуальным окружением ранее, взгляните на посвященный этому блог пост на английском языке - Python virtual environments tutorial using Virtualenv and Poetry.

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

📌Примечание: использование виртуальной среды не является строгим требованием.

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

pip install google-search-results
pip install pandas

Процесс​

34244ee43ad2efeaac03399bbade32f7.png

Если объяснение не нужно:

3240be2ef2392f260dadf32eae9cc4bd.png

Органические результаты​

import os
from serpapi import GoogleSearch
from urllib.parse import urlsplit, parse_qsl


def organic_results():
print("extracting organic results..")

params = {
"api_key": os.getenv("API_KEY"), # ключ для аутентификации в SerpApi
"engine": "google_scholar",
"q": "minecraft redstone system structure characteristics strength", # поисковый запрос
"hl": "en", # язык
"as_ylo": "2017", # с 2017
"as_yhi": "2021", # до 2021
"start": "0" # первая страница
}

search = GoogleSearch(params)

organic_results_data = []

loop_is_true = True

while loop_is_true:
results = search.get_dict()

print(f"Currently extracting page №{results['serpapi_pagination']['current']}..")

for result in results["organic_results"]:
position = result["position"]
title = result["title"]
publication_info_summary = result["publication_info"]["summary"]
result_id = result["result_id"]
link = result.get("link")
result_type = result.get("type")
snippet = result.get("snippet")

try:
file_title = result["resources"][0]["title"]
except: file_title = None

try:
file_link = result["resources"][0]["link"]
except: file_link = None

try:
file_format = result["resources"][0]["file_format"]
except: file_format = None

try:
cited_by_count = int(result["inline_links"]["cited_by"]["total"])
except: cited_by_count = None

cited_by_id = result.get("inline_links", {}).get("cited_by", {}).get("cites_id", {})
cited_by_link = result.get("inline_links", {}).get("cited_by", {}).get("link", {})

try:
total_versions = int(result["inline_links"]["versions"]["total"])
except: total_versions = None

all_versions_link = result.get("inline_links", {}).get("versions", {}).get("link", {})
all_versions_id = result.get("inline_links", {}).get("versions", {}).get("cluster_id", {})

organic_results_data.append({
"page_number": results["serpapi_pagination"]["current"],
"position": position + 1,
"result_type": result_type,
"title": title,
"link": link,
"result_id": result_id,
"publication_info_summary": publication_info_summary,
"snippet": snippet,
"cited_by_count": cited_by_count,
"cited_by_link": cited_by_link,
"cited_by_id": cited_by_id,
"total_versions": total_versions,
"all_versions_link": all_versions_link,
"all_versions_id": all_versions_id,
"file_format": file_format,
"file_title": file_title,
"file_link": file_link,
})

if "next" in results["serpapi_pagination"]:
search.params_dict.update(dict(parse_qsl(urlsplit(results["serpapi_pagination"]["next"]).query)))
else:
loop_is_true = False

return organic_results_data

Объяснение парсинга органических результатов используя пагинацию​

Импортируем os, serpapi, urllib библиотеки:

import os
from serpapi import GoogleSearch
from urllib.parse import urlsplit, parse_qsl
Создаем и передаем поисковые параметры в GoogleSearch() где происходит все извлечение данных на бэкенде SerpApi:

params = {
"api_key": os.getenv("API_KEY"), # ключ для аутентификации в SerpApi
"engine": "google_scholar",
"q": "minecraft redstone system structure characteristics strength", # поисковый запрос
"hl": "en", # язык
"as_ylo": "2017", # с 2017
"as_yhi": "2021", # до 2021
"start": "0" # первая страница
}

search = GoogleSearch(params) # извлечение данных происходит тут
Создаём временный список list() для того чтобы сохранить данные которые будут дальше использоваться для сохранения в CSV или переданыcite_results() функции:

organic_results_data = []
Создаём while цикл для парсинга данных со всех доступных страниц:

loop_is_true = True

while loop_is_true:
results = search.get_dict()

# парсинг данных происходит тутачки..

if "next" in results["serpapi_pagination"]:
search.params_dict.update(dict(parse_qsl(urlsplit(results["serpapi_pagination"]["next"]).query)))
else:
loop_is_true = False

  • Если нет ссылки на следующую "next" страницу - while прекратится установив loop_is_true на False.
  • Если есть ссылка на следующую "next" страницу, search.params_dict.update разберет ссылку на части и передаст её к GoogleSearch(params) для результатов с новой страницы.
Парсим данные в for цикле:

for result in results["organic_results"]:
position = result["position"]
title = result["title"]
publication_info_summary = result["publication_info"]["summary"]
result_id = result["result_id"]
link = result.get("link")
result_type = result.get("type")
snippet = result.get("snippet")

try:
file_title = result["resources"][0]["title"]
except: file_title = None

try:
file_link = result["resources"][0]["link"]
except: file_link = None

try:
file_format = result["resources"][0]["file_format"]
except: file_format = None

try:
cited_by_count = int(result["inline_links"]["cited_by"]["total"])
except: cited_by_count = None

cited_by_id = result.get("inline_links", {}).get("cited_by", {}).get("cites_id", {})
cited_by_link = result.get("inline_links", {}).get("cited_by", {}).get("link", {})

try:
total_versions = int(result["inline_links"]["versions"]["total"])
except: total_versions = None

all_versions_link = result.get("inline_links", {}).get("versions", {}).get("link", {})
all_versions_id = result.get("inline_links", {}).get("versions", {}).get("cluster_id", {})

  • try/except блоки были использованы для обработки None значений когда они отсутствуют из Google бэкенда.
Если объединить все в один try блок, извлеченные данные могут быть неаккуратны, иными словами если ссылка или описание на самом деле есть в выдаче, вместо этого оно вернёт None, поэтому здесь много try/except блоков.

Добавляем извлеченные данные во временный list() список:

organic_results_data = []

# тут парсинг и while цикл...

organic_results_data.append({
"page_number": results["serpapi_pagination"]["current"],
"position": position + 1,
"result_type": result_type,
"title": title,
"link": link,
"result_id": result_id,
"publication_info_summary": publication_info_summary,
"snippet": snippet,
"cited_by_count": cited_by_count,
"cited_by_link": cited_by_link,
"cited_by_id": cited_by_id,
"total_versions": total_versions,
"all_versions_link": all_versions_link,
"all_versions_id": all_versions_id,
"file_format": file_format,
"file_title": file_title,
"file_link": file_link,
})
Возвращаем временный list() список с данными которые будут использоваться позже при парсинге Цитируемых результатов:

return organic_results_data

6a5ec1cf1685cad4ca9c64b1a0547ba2.png

Цитируемые результаты​

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

Если у вас уже есть result_ids, вы можете пропустить парсинг Органических результатов:

# если у вас есть список result_ids

result_ids = ["FDc6HiktlqEJ"..."FDc6Hikt21J"]
for citation in result_ids:
params = {
"api_key": "API_KEY", # ключ для аутентификации в SerpApi
"engine": "google_scholar_cite", # движок для парсинга цитируемых результатов
"q": citation # FDc6HiktlqEJ ... FDc6Hikt21J
}
search = GoogleSearch(params)
results = search.get_dict()
# дальнейший код парсинга..
Ниже примера кода парсинга цитируемых результатов вы так же найдете пошаговое объяснение того что в нём происходит.

import os
from serpapi import GoogleSearch
from google_scholar_organic_results import organic_results

def cite_results():

print("extracting cite results..")

citation_results = []

for citation in organic_results():
params = {
"api_key": os.getenv("API_KEY"), # ключ для аутентификации в SerpApi
"engine": "google_scholar_cite", # # движок для парсинга цитируемых результатов
"q": citation["result_id"] # # FDc6HiktlqEJ ... FDc6Hikt21J
}

search = GoogleSearch(params)
results = search.get_dict()

print(f"Currently extracting {citation['result_id']} citation ID.")

for result in results["citations"]:
cite_title = result["title"]
cite_snippet = result["snippet"]

citation_results.append({
"organic_result_title": citation["title"],
"organic_result_link": citation["link"],
"citation_title": cite_title,
"citation_snippet": cite_snippet
})

return citation_results

Объяснение парсинга цитируемых результатов​

Создаём временный список list() для хранения извлеченных данных:

citation_results = []
Создаём for цикл для итерации по organic_results() результатам и передаем result_id в "q" поисковый запрос:

for citation in organic_results():
params = {
"api_key": os.getenv("API_KEY"), # ключ для аутентификации в SerpApi
"engine": "google_scholar_cite", # # движок для парсинга цитируемых результатов
"q": citation["result_id"] # # FDc6HiktlqEJ ... FDc6Hikt21J
}

search = GoogleSearch(params) # парсинг на бэкенде SerpApi
results = search.get_dict() # JSON конвертируется в словарь
Создаём второй for цикл и достукиваемся к данный таким же способом как и до словаря:

for result in results["citations"]:
cite_title = result["title"]
cite_snippet = result["snippet"]
Добавляем извелченные данные во временный список list() как словарь:

citation_results.append({
"organic_result_title": citation["title"], # чтобы понимать откуда берутся Цитируемые результаты
"organic_result_link": citation["link"], # чтобы понимать откуда берутся Цитируемые результаты
"citation_title": cite_title,
"citation_snippet": cite_snippet
})
Возвращаем временный список list():

return citation_results

13b1dcc8dd67f8eb33bd0c2b5d941c3e.png

Сохраняем в CSV​

Нам только нужно передать возвращенные данные из органических и цитируемых результатов в DataFrame data аргумент и сохранить to_csv().

import pandas as pd
from google_scholar_organic_results import organic_results
from google_scholar_cite_results import cite_results

print("waiting for organic results to save..")
pd.DataFrame(data=organic_results())
.to_csv("google_scholar_organic_results.csv", encoding="utf-8", index=False)

print("waiting for cite results to save..")
pd.DataFrame(data=cite_results())
.to_csv("google_scholar_citation_results.csv", encoding="utf-8", index=False)

Объяснение процесса сохранения в CSV​

Импортируем organic_results() и cite_results() откуда возвращаются данные, и библиотеку pandas:

import pandas as pd
from google_scholar_organic_results import organic_results
from google_scholar_cite_results import cite_results
Сохраняем органические результаты to_csv():

pd.DataFrame(data=organic_results()) \
.to_csv("google_scholar_organic_results.csv", encoding="utf-8", index=False)
Сохраняем цитируемые результаты to_csv():

pd.DataFrame(data=cite_results()) \
.to_csv("google_scholar_citation_results.csv", encoding="utf-8", index=False)
  • data аргумент внутри DataFrame это извлеченные данные.
  • encoding='utf-8' аргумент просто для того чтобы все было корректно сохранено. Я использовал этот аргумент явно, несмотря на то что это его дефолтное значение.
  • index=False аргумент чтобы убрать дефолтные номера строк pandas.

ec90ad47f947e5deb6f803b3e73b8685.png

Сохраняем в SQLite​

После этой секции вы узнаете о том как:

  • сохранять данные в SQLite используя pandas,
  • функционирует SQLite,
  • подключаться и разрывать соединение с SQLite,
  • создавать и удалять таблицы/колонки,
  • добавлять данные в for цикле.
Пример того как функционирует SQLite:

1. открывается соединение
2. транзакция начинается
3. выполняется инструкция
4. транзакция завершается
5. закрывается соединение

Сохранение данные в SQLite используя pandas​

# https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_sql.html
import sqlite3
import pandas as pd
from google_scholar_organic_results import organic_results
from google_scholar_cite_results import cite_results

conn = sqlite3.connect("google_scholar_results.db")

# создавать таблицу ручными SQL запросами не нужно,
# pandas это сделает автоматически.

# сохраняет органические результаты в SQLite
pd.DataFrame(organic_results()).to_sql(name="google_scholar_organic_results",
con=conn,
if_exists="append",
index=False)

# сохраняет цитируемые результаты в SQLite
pd.DataFrame(cite_results()).to_sql(name="google_scholar_cite_results",
con=conn,
if_exists="append",
index=False)

conn.commit()
conn.close()
  • name это название SQL таблицы.
  • con это соединение с базой данных.
  • if_exists скажет pandas как себя вести если таблица уже существует. По умолчанию оно не сработает "fail" и вызовет raise ошибку ValueError. В данном случае pandas будет добавлять данные.
  • index=False чтобы убрать индекс столбцов от DataFrame.

Другой способ сохранения данных вручную используя запросы SQLite​

import sqlite3

conn = sqlite3.connect("google_scholar_results.db")

conn.execute("""CREATE TABLE google_scholar_organic_results (
page_number integer,
position integer,
result_type text,
title text,
link text,
snippet text,
result_id text,
publication_info_summary text,
cited_by_count integer,
cited_by_link text,
cited_by_id text,
total_versions integer,
all_versions_link text,
all_versions_id text,
file_format text,
file_title text,
file_link text)""")
conn.commit()

conn.execute("""CREATE TABLE google_scholar_cite_results (
organic_results_title text,
organic_results_link text,
citation_title text,
citation_link text)""")
conn.commit()

# сохраняем органические результаты
for item in organic_results():
conn.execute("""INSERT INTO google_scholar_organic_results
VALUES :)page_number,
:position,
:result_type,
:title,
:link,
:snippet,
:result_id,
:publication_info_summary,
:cited_by_count,
:cited_by_link,
:cited_by_id,
:total_versions,
:all_versions_link,
:all_versions_id,
:file_format,
:file_title,
:file_link)""",
{"page_number": item["page_number"],
"position": item["position"],
"result_type": item["type"],
"title": item["title"],
"link": item["link"],
"snippet": item["snippet"],
"result_id": item["result_id"],
"publication_info_summary": item["publication_info_summary"],
"cited_by_count": item["cited_by_count"],
"cited_by_link": item["cited_by_link"],
"cited_by_id": item["cited_by_id"],
"total_versions": item["total_versions"],
"all_versions_link": item["all_versions_link"],
"all_versions_id": item["all_versions_id"],
"file_format": item["file_format"],
"file_title": item["file_title"],
"file_link": item["file_link"]})
conn.commit()

# сохраняем цитируемые результаты
for cite_result in cite_results():
conn.execute("""INSERT INTO google_scholar_cite_results
VALUES :)organic_result_title,
:eek:rganic_result_link,
:citation_title,
:citation_snippet)""",
{"organic_result_title": cite_result["organic_result_title"],
"organic_result_link": cite_result["organic_result_link"],
"citation_title": cite_result["citation_title"],
"citation_snippet": cite_result["citation_snippet"]})

conn.commit()
conn.close() # явно лучше, чем неявно

Объяснение сохранения извлеченных данных вручную прописывая запросы SQLite​

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

import sqlite3
Соединяемся с существующей базе данных или даём новое имя и библиотека создаст базу данных:

conn = sqlite3.connect("google_scholar_results.db")
Создаём таблицу органические результаты, указываем тип данных и применяем изменения:

conn.execute("""CREATE TABLE google_scholar_organic_results (
page_number integer,
position integer,
result_type text,
title text,
link text,
snippet text,
result_id text,
publication_info_summary text,
cited_by_count integer,
cited_by_link text,
cited_by_id text,
total_versions integer,
all_versions_link text,
all_versions_id text,
file_format text,
file_title text,
file_link text)""")
conn.commit()
Создаём таблицу цитируемые результаты, указываем тип данных и применяем изменения:

conn.execute("""CREATE TABLE google_scholar_cite_results (
organic_results_title text,
organic_results_link text,
citation_title text,
citation_link text)""")
conn.commit()
Добавляем извлеченные органические результаты в таблицу используя for цикл:

for item in organic_results():
conn.execute("""INSERT INTO google_scholar_organic_results
VALUES :)page_number,
:position,
:result_type,
:title,
:link,
:snippet,
:result_id,
:publication_info_summary,
:cited_by_count,
:cited_by_link,
:cited_by_id,
:total_versions,
:all_versions_link,
:all_versions_id,
:file_format,
:file_title,
:file_link)""",
{"page_number": item["page_number"],
"position": item["position"],
"result_type": item["type"],
"title": item["title"],
"link": item["link"],
"snippet": item["snippet"],
"result_id": item["result_id"],
"publication_info_summary": item["publication_info_summary"],
"cited_by_count": item["cited_by_count"],
"cited_by_link": item["cited_by_link"],
"cited_by_id": item["cited_by_id"],
"total_versions": item["total_versions"],
"all_versions_link": item["all_versions_link"],
"all_versions_id": item["all_versions_id"],
"file_format": item["file_format"],
"file_title": item["file_title"],
"file_link": item["file_link"]})
conn.commit()
Добавляем извлеченные цитируемые результаты в таблицу используя for цикл:

for cite_result in cite_results():
conn.execute("""INSERT INTO google_scholar_cite_results
VALUES :)organic_result_title,
:eek:rganic_result_link,
:citation_title,
:citation_snippet)""",
{"organic_result_title": cite_result["organic_result_title"],
"organic_result_link": cite_result["organic_result_link"],
"citation_title": cite_result["citation_title"],
"citation_snippet": cite_result["citation_snippet"]})
conn.commit()
Закрываем cоединение с базой данных:

conn.close()
Дополнительные полезные команды:

# удалить все данные из таблицы
conn.execute("DELETE FROM google_scholar_organic_results")

# удалить таблицу
conn.execute("DROP TABLE google_scholar_organic_results")

# удалить колонку
conn.execute("ALTER TABLE google_scholar_organic_results DROP COLUMN authors")

# добавить колнку
conn.execute("ALTER TABLE google_scholar_organic_results ADD COLUMN snippet text")

Код целиком - парсинг​

import os
from serpapi import GoogleSearch
from urllib.parse import urlsplit, parse_qsl


def organic_results():
print("extracting organic results..")

params = {
"api_key": os.getenv("API_KEY"),
"engine": "google_scholar",
"q": "minecraft redstone system structure characteristics strength", # поисковый запрос
"hl": "en", # язык
"as_ylo": "2017", # от 2017
"as_yhi": "2021", # до 2021
"start": "0"
}

search = GoogleSearch(params)

organic_results_data = []

loop_is_true = True

while loop_is_true:
results = search.get_dict()

print(f"Currently extracting page №{results['serpapi_pagination']['current']}..")

for result in results["organic_results"]:
position = result["position"]
title = result["title"]
publication_info_summary = result["publication_info"]["summary"]
result_id = result["result_id"]
link = result.get("link")
result_type = result.get("type")
snippet = result.get("snippet")

try:
file_title = result["resources"][0]["title"]
except: file_title = None

try:
file_link = result["resources"][0]["link"]
except: file_link = None

try:
file_format = result["resources"][0]["file_format"]
except: file_format = None

try:
cited_by_count = int(result["inline_links"]["cited_by"]["total"])
except: cited_by_count = None

cited_by_id = result.get("inline_links", {}).get("cited_by", {}).get("cites_id", {})
cited_by_link = result.get("inline_links", {}).get("cited_by", {}).get("link", {})

try:
total_versions = int(result["inline_links"]["versions"]["total"])
except: total_versions = None

all_versions_link = result.get("inline_links", {}).get("versions", {}).get("link", {})
all_versions_id = result.get("inline_links", {}).get("versions", {}).get("cluster_id", {})

organic_results_data.append({
"page_number": results["serpapi_pagination"]["current"],
"position": position + 1,
"result_type": result_type,
"title": title,
"link": link,
"result_id": result_id,
"publication_info_summary": publication_info_summary,
"snippet": snippet,
"cited_by_count": cited_by_count,
"cited_by_link": cited_by_link,
"cited_by_id": cited_by_id,
"total_versions": total_versions,
"all_versions_link": all_versions_link,
"all_versions_id": all_versions_id,
"file_format": file_format,
"file_title": file_title,
"file_link": file_link,
})

if "next" in results["serpapi_pagination"]:
search.params_dict.update(dict(parse_qsl(urlsplit(results["serpapi_pagination"]["next"]).query)))
else:
loop_is_true = False

return organic_results_data


def cite_results():

print("extracting cite results..")

citation_results = []

for citation in organic_results():
params = {
"api_key": os.getenv("API_KEY"),
"engine": "google_scholar_cite",
"q": citation["result_id"]
}

search = GoogleSearch(params)
results = search.get_dict()

print(f"Currently extracting {citation['result_id']} citation ID.")

for result in results["citations"]:
cite_title = result["title"]
cite_snippet = result["snippet"]

citation_results.append({
"organic_result_title": citation["title"],
"organic_result_link": citation["link"],
"citation_title": cite_title,
"citation_snippet": cite_snippet
})

return citation_results



# пример вывода при парсинге органических результатов и сохранение в SQL:
'''
extracting organic results..
Currently extracting page №1..
Currently extracting page №2..
Currently extracting page №3..
Currently extracting page №4..
Currently extracting page №5..
Currently extracting page №6..
Done extracting organic results.
Saved to SQL Lite database.
'''

Код целиком - сохранение​

import pandas as pd
import sqlite3
from google_scholar_organic_results import organic_results
from google_scholar_cite_results import cite_results

# Один из способов сохранить данные в БД используя Pandas
print("waiting for organic results to save..")
organic_df = pd.DataFrame(data=organic_results())
organic_df.to_csv("google_scholar_organic_results.csv", encoding="utf-8", index=False)

print("waiting for cite results to save..")
cite_df = pd.DataFrame(data=cite_results())
cite_df.to_csv("google_scholar_citation_results.csv", encoding="utf-8", index=False)

# ------------------------------

# Другой способ сохранить данные в БФ в ручную прописывая SQLite запросы
conn = sqlite3.connect("google_scholar_results.db")

conn.execute("""CREATE TABLE google_scholar_organic_results (
page_number integer,
position integer,
result_type text,
title text,
link text,
snippet text,
result_id text,
publication_info_summary text,
cited_by_count integer,
cited_by_link text,
cited_by_id text,
total_versions integer,
all_versions_link text,
all_versions_id text,
file_format text,
file_title text,
file_link text)""")
conn.commit()


conn.execute("""CREATE TABLE google_scholar_cite_results (
organic_results_title text,
organic_results_link text,
citation_title text,
citation_link text)""")
conn.commit()

for item in organic_results():
conn.execute("""INSERT INTO google_scholar_organic_results
VALUES :)page_number,
:position,
:result_type,
:title,
:link,
:snippet,
:result_id,
:publication_info_summary,
:cited_by_count,
:cited_by_link,
:cited_by_id,
:total_versions,
:all_versions_link,
:all_versions_id,
:file_format,
:file_title,
:file_link)""",
{"page_number": item["page_number"],
"position": item["position"],
"result_type": item["type"],
"title": item["title"],
"link": item["link"],
"snippet": item["snippet"],
"result_id": item["result_id"],
"publication_info_summary": item["publication_info_summary"],
"cited_by_count": item["cited_by_count"],
"cited_by_link": item["cited_by_link"],
"cited_by_id": item["cited_by_id"],
"total_versions": item["total_versions"],
"all_versions_link": item["all_versions_link"],
"all_versions_id": item["all_versions_id"],
"file_format": item["file_format"],
"file_title": item["file_title"],
"file_link": item["file_link"]})
conn.commit()


for cite_result in cite_results():
conn.execute("""INSERT INTO google_scholar_cite_results
VALUES :)organic_result_title,
:eek:rganic_result_link,
:citation_title,
:citation_snippet)""",
{"organic_result_title": cite_result["organic_result_title"],
"organic_result_link": cite_result["organic_result_link"],
"citation_title": cite_result["citation_title"],
"citation_snippet": cite_result["citation_snippet"]})

conn.commit()
conn.close()
print("Saved to SQL Lite database.")


# пример вывода:
'''
extracting organic results..
Currently extracting page №1..
...
Currently extracting page №4..
extracting cite results..
extracting organic results..
Currently extracting page №1..
...
Currently extracting page №4..
Currently extracting 60l4wsP6Ps0J citation ID.
Currently extracting 9hkhIFu_BhAJ citation ID.
...
Saved to SQL Lite database.
'''

Ссылки​


Что дальше​

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

Следующий блог пост будет о парсинге Профилей с пагинацией, а так же Авторских результатов.

Если вы хотите парсить данные без необходимости писать парсер с нуля, разбираться как обойти блокировки от поисковых систем, как увеличить объем запросов, или, как парсить данные с JavaScript - попробуйте SerpApi или свяжитесь с SerpApi.

 
Сверху