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

Часы
15.02.2025
Часы
15.02.2025
Часы
6 минут
Глазик
175
Сердечки
0
Соединённые точки
0
Соединённые точки
0
Соединённые точки
0

Про что и для кого эта статья

Эта статья про то как можно написать собственный парсер поисковой выдачи, бесплатно и за 5 минут. Без использования таких наворотов как прокси или bs4. Никаких сторонних программ для обхода капчи и(или) имитаторов деятельности пользователя в браузере, т.е. Селениум, например.
Она предназначена для начинающих SEO-специалистов, которые немного шарят в программировании и понимают python-синтаксис, но у которых не очень много свободных денег.
И как же я собираюсь, парсить поисковую выдачу google? Всё просто, я подключусь к Google Search API, у которого есть бесплатный план в виде 100 запросов в сутки. Для владельца маленького сайта самый раз. Вот готовый проект парсера гугл поиска.

Создание ключа и id поисковой системы

Чтобы получить возможность пользоваться API от гугла, нам нужно получить ключ доступа и id поисковой системы. Для начала, создадим собственную поисковую систему. Переходя по адресу https://programmablesearchengine.google.com/controlpanel/all, нажми Добавить и заполни все поля формы.
Тебя перенаправит на следующую страницу. Теперь на этой странице ты можешь получить свой id.
ID есть, осталось только получить API-ключ. Заходим на эту страницу, регистрируемся если надо https://console.cloud.google.com/apis/dashboard?inv=1&invt=AbppVQ На этой странице нужно будет создать новый проект. Кликни сюда:
Дальше заполни все поля и всё готово. Создадим API ключ. Перейдём в Credentials, либо по ссылке, либо по кнопке (。・∀・)ノ゙:
Создадим наконец API-ключ:
После всех этих шагов тебе удалось создать свой собственный API-ключ к собственной поисковой системе. Скопируй его и сохрани где-нибудь.

Пишем парсер

Базовая настройка и подготовка

У нас всё есть, осталось только написать парсер. Создадим виртуальное окружение, установим необходимые пакеты и создадим парочку директорий:
mkdir MyParser
mkdir MyParser/data
mkdir MyParser/data/serp
mkdir MyParser/data/temp
New-Item MyParser/main.py
New-Item MyParser/config.json
python -m venv .venv
./.venv/Scripts/activate
pip install requests pandas openpyxl
Для Windows/PowerShell
mkdir MyParser
mkdir MyParser/data
mkdir MyParser/data/serp
mkdir MyParser/data/temp
touch MyParser/main.py
touch MyParser/config.json
python -m venv .venv
source ./.venv/bin/activate
pip install requests pandas openpyxl
Для Linux/Bash
Установка pandas и openpyxl необязательны, ибо если не хочешь сохранять результаты парсинга в XLSX файлы, то и не надо. Я буду, ибо мне так удобнее. В директории data будут храниться наши временные JSON файлы и сами результаты, либо те же JSON, либо XLSX таблицы.

Конфигурационный файл

Так же мой парсер будет иметь конфигурационный файл - config.json, откуда он сможет узнать, как ему следует обрабатывать запросы. Вот содержание конфигурационного файла, скопируй и вставь:
{
"key": "11111111111111111111111111111111111",
"cx": "11111111111111111",
"save_to": "exel",
"title": true,
"description": false,
"url": true,
"depth": 1
}

Таково вот, общее описание каждого из ключа:
  1. key - недавно созданный нами API-ключ
  2. cx - id созданный в начале поисковой системы
  3. save_to - позволяет определять как сохранять результат, допустимые значения это exel и json.
  4. depth - сколько страниц поисковой выдачи спарсить; гугл позволяет получить максимум 10 страниц по 10 позиций каждая
  5. title, description и url - то, что парсить

Скрипт

Данный скрипт разработан таким образом, чтобы принимать аргументы из командной строки. Первый это -q, сам запрос. Второй это путь до файла конфигурации -C. Сделал я это при помощи argparse модуля python. Весь его функционал реализуется в функции run():
def run():
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-q', type=str, help='Query to parse', metavar='QUERY', required=True, nargs='*')
parser.add_argument('-C', type=str, help='Path to config, in json format', metavar='CONFIG_FILE', required=True, nargs=1)
args = parser.parse_args()
# query
raw_query = ''.join(word + ' ' for word in args.q)
if raw_query is None:
return
query = quote(raw_query)
# check if config exist
options = {
'key': '',
'cx': '',
'save_to': '',
'title': '',
'description': '',
'url': '',
'depth':''
}
with open(args.C[0], 'r') as file:
data = json.loads(file.read())
for key in data:
if options.get(key) is not None:
options[key] = data[key]
else:
print(f'ERROR: Something went wrong in your config file, {key}')
return False

# check depth
if options['depth'] > 10:
print('WARNING: Google Search API allowed only 100 search results to be available')
options['depth'] = 10
else:
options['depth'] = data['depth']
serp_scrape_init(query, options)
serp_page_scrape(query, options)
В этой функции создаётся argparse объект, настраивается и после происходит обработка файла конфигурации. На самом дне этой функции идёт вызов serp_scrape_init и serp_page_scrape. Разберёмся с ними по порядку.
Работой с Google Search API выполняет первая функция serp_scrape_init. Хотя и работай это назвать сложно. Мы просто делаем запрос по вот этому URL:
https://www.googleapis.com/customsearch/v1?key={options['key']}&cx={options['cx']}&q={query}&num=10&start={i * 10 + 1}
Важно понимать, нам нужно пройти все возможный страницы которые отдаёт гугл. Для этого используются такие вот параметры в адресе, num и start. Первый отвечает за то, сколько сайтов возвращать при одном запросе (максимум 10). Второй параметр проходит все страницы с шагом в 10. Вообще есть куда больше параметров для запросов, со всеми ими можно ознакомиться здесь. По итогу, наша функция имеет следующий вид:
def serp_scrape_init(query: str, options: dict = {}) -> list:
for i in range(0, options['depth']):
response = requests.get(f'https://www.googleapis.com/customsearch/v1?key={options['key']}&cx={options['cx']}&q={query}&num=10&start={i * 10 + 1}')
save_to_json(f'./data/temp/{query}_{i*10 + 1}-{i*10 + 10}.json',response.json())
Как результат работы, функция создаёт JSON файлы, которые после будет обрабатываться serp_page_scrape. Собственно говоря, о ней.
def serp_page_scrape(query: str, options: dict) -> list:
data = []
for i in range(0, options['depth']):
try:
with open(f'./data/temp/{query}_{i*10 + 1}-{i*10 + 10}.json', 'r+', encoding='utf-8') as file:
data_temp = json.loads(file.read())
for item in data_temp['items']:
title = None
if options['title']:
title = item['title']
description = None
if options['description']:
description = item['snippet']
url = None
if options['url']:
url = item['link']

data.append({
'title': title,
'description': description,
'url': url,
})
except:
pass
if options['save_to'] == 'json':
save_to_json(f'./data/serp/{query}.json', data)
else:
save_to_exel(f'./data/serp/{query}.xlsx', data)

return data
Ни чего экстраординарного, она просто открывает ранее созданные JSON файлы и сохраняет то, что было указанно в файле конфигурации. И на этом всё. Теперь, мы по факту получили маленький гугл в консоли. Вот пример использования:
python main.py -q Самые большие кошки на планете -С config.json
А вот полный код скрипта и файла main.py:
import json
import argparse
import requests
import pandas
from urllib.parse import quote, unquote


def save_to_json(path, list):
with open(path, 'w', encoding='utf-8') as file:
json.dump(list, file, indent=2, ensure_ascii=False)
file.close()

def save_to_exel(path, data):
frame = pandas.DataFrame({
'title': [],
'link': [],
'description': []
})
for indx, entry in enumerate(data):
frame.at[indx, 'title'] = entry['title']
frame.at[indx, 'link'] = entry['url']
frame.at[indx, 'description'] = entry['description']
frame.to_excel(path, index=False )

def serp_page_scrape(query: str, options: dict) -> list:
data = []
for i in range(0, options['depth']):
try:
with open(f'./data/temp/{query}_{i*10 + 1}-{i*10 + 10}.json', 'r+', encoding='utf-8') as file:
data_temp = json.loads(file.read())
for item in data_temp['items']:
title = None
if options['title']:
title = item['title']
description = None
if options['description']:
description = item['snippet']
url = None
if options['url']:
url = item['link']

data.append({
'title': title,
'description': description,
'url': url,
})
except:
pass
if options['save_to'] == 'json':
save_to_json(f'./data/serp/{query}.json', data)
else:
save_to_exel(f'./data/serp/{query}.xlsx', data)

return data

def serp_scrape_init(query: str, options: dict = {}) -> list:
print(f'Query: {unquote(query)},\nOptions: title={options['title']} | description={options['description']} | urls={options['url']} | depth={options['depth']} | save to={options['save_to']}')
for i in range(0, options['depth']):
response = requests.get(f'https://www.googleapis.com/customsearch/v1?key={options['key']}&cx={options['cx']}&q={query}&num=10&start={i * 10 + 1}')
save_to_json(f'./data/temp/{query}_{i*10 + 1}-{i*10 + 10}.json',response.json())

def run():
# This is going to be only in standalone script
# Get the options and query from CLI
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-q', type=str, help='Query to parse', metavar='QUERY', required=True, nargs='*')
parser.add_argument('-C', type=str, help='Path to config, in json format', metavar='CONFIG_FILE', required=True, nargs=1)
args = parser.parse_args()
# query
raw_query = ''.join(word + ' ' for word in args.q)
if raw_query is None:
return
query = quote(raw_query)
# check if config exist
options = {
'key': '',
'cx': '',
'save_to': '',
'title': '',
'description': '',
'url': '',
'depth':''
}
with open(args.C[0], 'r') as file:
data = json.loads(file.read())
for key in data:
if options.get(key) is not None:
options[key] = data[key]
else:
print(f'ERROR: Something went wrong in your config file, {key}')
return False

# check depth
if options['depth'] > 10:
print('WARNING: Google Search API allowed only 100 search results to be available')
options['depth'] = 10
else:
options['depth'] = data['depth']
serp_scrape_init(query, options)
serp_page_scrape(query, options)

if __name__ == "__main__":
run()

Заключение

Знаешь, я изначально планировал написать парсер на стеке BeautifulSoup4 + Selenium + Python. Но немного погуглив, нет я не нашёл официальный туториал от google, как создать легальный парсер поисковой выдачи. Мне выбивало сайты агенств и компаний, которые предлагают сделать то же самое только за деньги.
Нет, конечно. Если ты крупная компания и тебе нужно делать 1000 запросов в секунду, то Google Search API, может предоставить дополнительные лимиты за небольшую плату. Очень небольшую, в сравнении с "не названными" компаниями и сайтами. Вот такие вот дела. Если хочешь узнать больше об Google Search API загляни на их официальный блог. Он очень информативен.


Комментарии

(0)

captcha
Отправить
Сейчас тут пусто. Буть первым (o゚v゚)ノ

Другое