Pull to refresh

Простой метапоисковый алгоритм на Python

Reading time3 min
Views20K

Лирическое отступление


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

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

Когда лень работать руками


Первая и самая очевидная для меня мысль – написать простой метапоисковый алгоритм на Python. Другими словами, вся автоматизация сводится к использованию выдачи другой поисковой машины (Google Search) за неимением своих баз данных. Сразу оговорюсь, есть уже готовые библиотеки, решающие подобную задачу, например pygoogle.

Ближе к делу


Для HTTP-запросов я использовал requests, а для извлечения ссылок из поисковой выдачи — библиотеку для парсинга BeautifulSoup. Вот что получилось:

from bs4 import BeautifulSoup
import requests
query = input('What are you searching for?:   ' )
url ='http://www.google.com/search?q='
page = requests.get(url + query)
soup = BeautifulSoup(page.text)
h3 = soup.find_all("h3",class_="r")
for elem in h3:
	elem=elem.contents[0]
	link=("https://www.google.com" + elem["href"])
	print(link)

Я дергал лишь ссылки на сайты, которые на странице результатов поиска Chrome находятся внутри тэгов {h3 class=«r»}.

Чтож, отлично, теперь попробуем забрать ссылки, обойдя несколько страниц браузера:

from bs4 import BeautifulSoup
import requests
query = input('What are you searching for?:  ' )
number = input('How many pages:  ' )
url ='http://www.google.com/search?q='
page = requests.get(url + query)
for index in range(int(number)):
	soup = BeautifulSoup(page.text)
	next_page=soup.find("a",class_="fl")
	next_link=("https://www.google.com"+next_page["href"])
	h3 = soup.find_all("h3",class_="r")
	for elem in h3:
		elem=elem.contents[0]
		link=("https://www.google.com" + elem["href"])
		print(link)
	page = requests.get(next_link)

Адрес следующей страницы Chrome хранит в тэге {a class=«fl»}.

Ну и напоследок попробуем достать информацию с какой-нибудь страницы и сделать из нее словарь для будущего рубрикатора. Забирать необходимую информацию будем с той же Википедии:

from bs4 import BeautifulSoup
import requests
dict=""
query = input('What are you searching for?: ' )
url ='http://www.google.com/search?q='
page = requests.get(url + query)
soup = BeautifulSoup(page.text)
h3 = soup.find_all("h3",class_="r")
for elem in h3:
	elem=elem.contents[0]
	elem = elem["href"]
	if "wikipedia" in elem:
		link=("https://www.google.com" + elem)
		break
page = requests.get(link)
soup = BeautifulSoup(page.text)
text = soup.find(id="mw-content-text")
p= text.find("p")
while p != None:
	dict+=p.get_text()+"\n"
	p = p.find_next("p")
dict=dict.split()

Для запроса «god» получается неплохой такой словарь на 3.500 терминов, который, по правде говоря, придется дорабатывать напильником, удаляя знаки препинания, ссылки, стоп-слова и прочий «мусор».

Вывод


Подводя итог проделанной работы, надо заметить, что словарь конечно получился «сырой» и «натаскивание» парсера на конкретный ресурс требует времени на изучение его структуры. Это наталкивает на простую мысль — генерацию обучающей выборки стоит осуществлять самому, или пользоваться готовыми базами данных.

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

Ссылки на используемый инструментарий


BeautifulSoup: www.crummy.com/software/BeautifulSoup
Requests: docs.python-requests.org/en/latest
Tags:
Hubs:
+6
Comments10

Articles

Change theme settings