Этот обучающий пост в блоге покажет вам, как очистить рейтинг позиции веб-сайта, заголовок, ссылку, отображаемую ссылку и фрагмент.
- Что такое поиск Naver
- "Вступление"
- Предпосылки
- Что будет соскабливать
- "Процесс"
- "Код"
- Ссылки
- Аутро
Что такое поиск Naver
Я уже отвечал на это в своем первом блоге о парсинге Результаты Naver News, там можно найти информацию о том, что такое Naver Search.
вступление
Этот обучающий пост в блоге является продолжением серии веб-скрейпинга Naver. Здесь вы увидите, как очистить рейтинг веб-сайта Naver Organic Results, заголовок, ссылку, отображаемую ссылку и фрагмент кода с помощью Python, используя библиотеки beautifulsoup
, requests
, lxml
.
Примечание. В этом сообщении блога показано, как извлечь данные, которые отображаются в разделе Что будет очищено.
Предпосылки и импорт
pip install requests
pip install lxml
pip install beautifulsoup4
- Базовые знания Python.
- Базовое знакомство с упомянутыми выше пакетами.
- Базовое понимание селекторов
CSS
, потому что вы увидите в основном использование методовselect()
/select_one()
beautifulsoup
, которые принимают селекторыCSS
.
Я написал специальный блог о парсинге веб-страниц с помощью CSS
селекторов, чтобы рассказать, что это такое, его плюсы и минусы и почему они важны с точки зрения парсинга веб-страниц.
Импорт
import requests, lxml
from bs4 import BeautifulSoup
Что будет очищено
Процесс
Если вам не нужно объяснение, переходите к разделу кода.
Нам нужно сделать три шага, чтобы сделать:
- Сохраните HTML локально, чтобы протестировать все, прежде чем делать много прямых запросов.
- Выберите
CSS
селекторов для всех необходимых данных. - Извлеките данные.
Сохраните HTML для локального тестирования синтаксического анализатора
Локальное сохранение HTML предотвращает блокировку или блокировку IP-адресов, особенно когда необходимо сделать несколько запросов к одному и тому же веб-сайту для тестирования кода.
Обычный пользователь не будет выполнять более 100 запросов за очень короткий промежуток времени и не будет делать одно и то же снова и снова (шаблон), как это делают скрипты, поэтому веб-сайты могут помечать такое поведение как необычный и заблокировать IP-адрес на некоторое время (может быть написано в ответе: requests.get("URL").text
) или навсегда.
import requests
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582" }
params = { "query": "bruce lee", "where": "web" # theres's also a "nexearch" param that will produce different results }
def save_naver_organic_results(): html = requests.get("https://search.naver.com/search.naver", params=params, headers=headers).text
# replacing every space to underline (_) so bruce lee will become bruce_lee query = params['query'].replace(" ", "_")
with open(f"{query}_naver_organic_results.html", mode="w") as file: file.write(html)
Теперь, что здесь происходит
Импортировать requests
библиотеку
import requests
Добавьте user-agent
и параметры запроса
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582" }
# query parameters params = { "query": "bruce lee", "where": "web" }
Я предпочитаю передавать параметры запроса в requests.get(params=params)
вместо того, чтобы оставлять их в URL-адресе. Я нахожу это более читаемым, например, давайте посмотрим на тот же самый URL:
params = { "where": "web", "sm": "top_hty", "fbm": "1", "ie": "utf8", "query": "bruce+lee" } requests.get("https://search.naver.com/search.naver", params=params)
# VS
requests.get("https://search.naver.com/search.naver?where=web&sm=top_hty&fbm=1&ie=utf8&query=bruce+lee") # Press F.
Что насчет user-agent
, он должен действовать как реальный визит пользователя, иначе запрос может быть отклонен. Вы можете прочитать больше об этом в другом моем сообщении в блоге о том, как уменьшить вероятность блокировки при просмотре веб-страниц поисковыми системами.
Выберите и протестируйте CSS
селекторов
Выбор контейнера (селектор CSS
, который содержит все необходимые данные), заголовка, ссылки, отображаемой ссылки и фрагмента.
GIF выше переводится как этот фрагмент кода:
for result in soup.select(".total_wrap"):
title = result.select_one(".total_tit").text.strip()
link = result.select_one(".total_tit .link_tit")["href"]
displayed_link = result.select_one(".total_source").text.strip()
snippet = result.select_one(".dsc_txt").text
Извлечь данные
import lxml, json from bs4 import BeautifulSoup
def extract_local_html_naver_organic_results(): with open("bruce_lee_naver_organic_results.html", mode="r") as html_file: html = html_file.read() soup = BeautifulSoup(html, "lxml")
data = []
for index, result in enumerate(soup.select(".total_wrap")): title = result.select_one(".total_tit").text.strip() link = result.select_one(".total_tit .link_tit")["href"] displayed_link = result.select_one(".total_source").text.strip() snippet = result.select_one(".dsc_txt").text
data.append({ "position": index + 1, # starts from 1, not from 0 "title": title, "link": link, "displayed_link": displayed_link, "snippet": snippet })
print(json.dumps(data, indent=2, ensure_ascii=False))
Теперь давайте разберем часть извлечения
Импортировать библиотеки bs4
, lxml
, json
import lxml, json
from bs4 import BeautifulSoup
Откройте сохраненный файл HTML, прочитайте его и передайте объекту BeautifulSoup()
и назначьте lxml
в качестве парсера HTML.
with open("bruce_lee_naver_organic_results.html", mode="r") as html_file:
html = html_file.read()
soup = BeautifulSoup(html, "lxml")
Создайте временный list()
для хранения извлеченных данных
data = []
Повторить и добавить как словарь к временному list()
Так как нам также нужно получить индекс (позиция в рейтинге), мы можем использовать метод enumerate()
, который добавляет счетчик к итерируемому объекту и возвращает его. Еще примеры.
Пример:
grocery = ["bread", "milk", "butter"] # iterable
for index, item in enumerate(grocery): print(f"{index} {item}\n") ''' 0 bread 1 milk 2 butter '''
Фактический код:
# in our case iterable is soup.select() since it returns an iterable as well for index, result in enumerate(soup.select(".total_wrap")): title = result.select_one(".total_tit").text.strip() link = result.select_one(".total_tit .link_tit")["href"] displayed_link = result.select_one(".total_source").text.strip() snippet = result.select_one(".dsc_txt").text
data.append({ "position": index + 1, # starts from 1, not from 0 "title": title, "link": link, "displayed_link": displayed_link, "snippet": snippet })
Полный код
Теперь, объединив все функции вместе, мы получим четыре (4) функции:
- Первая функция сохраняет HTML локально.
- Вторая функция открывает локальный HTML и вызывает функцию парсера.
- Третья функция делает фактический запрос и вызывает функцию парсера.
- Четвертая функция — это синтаксический анализатор, который вызывается второй и третьей функциями.
Примечание: первую и вторую функцию можно пропустить, если вы не очень хотите этого делать, но имейте в виду возможные последствия, о которых упомянули выше.
import requests import lxml, json from bs4 import BeautifulSoup
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582" }
params = { "query": "bruce lee", # search query "where": "web" # nexearch will produce different results }
# function that saves HTML locally def save_naver_organic_results(): html = requests.get("https://search.naver.com/search.naver", params=params, headers=headers).text
# replacing every spaces so bruce lee will become bruce_lee query = params['query'].replace(" ", "_")
with open(f"{query}_naver_organic_results.html", mode="w") as file: file.write(html)
# fucntion that opens local HTML and calls a parser function def extract_naver_organic_results_from_html(): with open("bruce_lee_naver_organic_results.html", mode="r") as html_file: html = html_file.read()
# calls naver_organic_results_parser() function to parse the page data = naver_organic_results_parser(html)
print(json.dumps(data, indent=2, ensure_ascii=False))
# function that make an actual request and calls a parser function def extract_naver_organic_results_from_url(): html = requests.get("https://search.naver.com/search.naver", params=params, headers=headers)
# calls naver_organic_results_parser() function to parse the page data = naver_organic_results_parser(html)
print(json.dumps(data, indent=2, ensure_ascii=False))
# parser that's being called by 2-3 functions def naver_organic_results_parser(html): soup = BeautifulSoup(html.text, "lxml")
data = []
for index, result in enumerate(soup.select(".total_wrap")): title = result.select_one(".total_tit").text.strip() link = result.select_one(".total_tit .link_tit")["href"] displayed_link = result.select_one(".total_source").text.strip() snippet = result.select_one(".dsc_txt").text
data.append({ "position": index + 1, # starts from 1, not from 0 "title": title, "link": link, "displayed_link": displayed_link, "snippet": snippet })
return data
Использование API органических результатов Naver Web
Кроме того, вы можете добиться тех же результатов, используя SerpApi. SerpApi — это платный API с бесплатным планом.
Разница в том, что нет необходимости создавать синтаксический анализатор с нуля, пытаясь выбрать правильные селекторы CSS
, и не злиться, когда определенные селекторы не работают так, как вы ожидали, плюс нет необходимости поддерживать синтаксический анализатор с течением времени, если что-то в HTML будет изменено, и при следующем запуске скрипт вылетит с ошибкой.
Кроме того, нет необходимости обходить блокировки от Google (или других поисковых систем), понимая, как масштабировать объем запросов, потому что это уже происходит под капотом у конечных пользователей с соответствующими планами. Попробуй на детской площадке.
Установить библиотеку SerpApi
pip install google-search-results
Пример кода для интеграции:
from serpapi import GoogleSearch import os, json
def serpapi_get_naver_organic_results(): params = { "api_key": os.getenv("API_KEY"), "engine": "naver", # search engine (Google, Bing, DuckDuckGo..) "query": "Bruce Lee", # search query "where": "web" }
search = GoogleSearch(params) results = search.get_dict()
data = []
for result in results["organic_results"]: data.append({ "position": result["position"], "title": result["title"], "link": result["link"], "displayed_link": result["displayed_link"], "snippet": result["snippet"] })
print(json.dumps(data, indent=2, ensure_ascii=False))
Давайте посмотрим, что здесь происходит
Импортировать библиотеки serpapi
, os
, json
from serpapi import GoogleSearch
import os, json
Передать параметры поиска в виде словаря ({}
)
params = {
"api_key": os.getenv("API_KEY"),
"engine": "naver", # search engine (Google, Bing, DuckDuckGo..)
"query": "Bruce Lee", # search query
"where": "web" # filter to extract data from organic results
}
Извлечение данных
Это происходит под капотом, поэтому вам не нужно думать об этих двух строках кода.
search = GoogleSearch(params) # data extraction
results = search.get_dict() # structured JSON which is being called later
Создайте list()
для временного хранения данных
data = []
Повторить и append()
извлечь данные в list()
как словарь ({}
)
for result in results["organic_results"]:
data.append({
"position": result["position"],
"title": result["title"],
"link": result["link"],
"displayed_link": result["displayed_link"],
"snippet": result["snippet"]
})
Распечатать добавленные данные
print(json.dumps(data, indent=2, ensure_ascii=False))
# ----------------
# part of the output
'''
[
{
"position": 1,
"title": "Bruce Lee",
"link": "https://brucelee.com/",
"displayed_link": "brucelee.com",
"snippet": "New Podcast Episode: #402 Flowing with Dustin Nguyen Watch + Listen to Episode “Your inspiration continues to guide us toward our personal liberation.” - Bruce Lee - More Podcast Episodes HBO Announces Order For Season 3 of Warrior! WARRIOR Seasons 1 & 2 Streaming Now on HBO & HBO Max “Warrior is still the best show you’re"
}
# other results..
]
'''
Если вам нужна дополнительная информация о планах, это объяснил ранее член команды SerpApi Джастин О'Хара в своем сообщении в блоге Разбивка подписок SerpApi (информация та же, за исключением того, что вам не нужно входить в SerpApi). сайт).
Ссылки
- Код в Online IDE (Replit)
- API органических результатов Naver Web
- СелекторГаджет
CSS
УжинCSS
Справочник по селекторам
Outro
Если вам есть чем поделиться, какие-либо вопросы, предложения или что-то, что не работает должным образом, не стесняйтесь оставлять комментарии в разделе комментариев или через Twitter в @dimitryzub или @serp_api.
С уважением,
Дмитрий, и остальная часть команды SerpApi.
Присоединяйтесь к нам на Reddit | Твиттер | Ютуб
Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку здесь.