Как парсить Yellow Pages с помощью Python и LXML?
В этом учебнике по парсингу мы рассмотрим, как парсить YellowPages.com с помощью Python и LXML, чтобы получить информацию о бизнесе на основе категории и города из Yellow Pages.
Чтобы использовать этот парсер Yellow Pages, давайте пройдемся по страницам Yellow Pages с данными о разных ресторанах в городе. Затем извлечем информацию о бизнесе из результатов первой страницы.
Какие данные мы извлекаем?
Вот поля данных, которые мы будем парсить:
- Рейтинги
- Название бизнеса
- Страницы бизнеса
- Номера телефонов
- Веб-сайт
- Название улицы
- Категория
- Рейтинги
- Регион
- Местоположение
- URL
- Почтовый индекс
Вот скриншот информации, которую мы будем парсить с Yellow Pages с использованием API Yellow Pages.
Как найти данные?
Сначала нам нужно найти данные, которые доступны на текущей странице в HTML-тегах, прежде чем начать создавать парсер Yellow Pages. Для этого вам следует понять HTML-теги содержимого страницы.
Если вы знаете Python и HTML, вам будет проще. Вам не требуются высокие навыки программирования для большей части этого руководства.
Давайте рассмотрим HTML-код веб-страницы и узнаем, где находятся данные. Мы собираемся сделать следующее:
-
Получить HTML-теги, которые содержат список ссылок, откуда мы хотим получить данные.
-
Получить ссылки из этого списка и извлечь данные.
Обзор HTML
Зачем нам нужно проверять элементы? — Чтобы получить любые элементы на веб-страницах с помощью пути XML.
Откройте веб-браузер (мы использовали Google Chrome) и перейдите по ссылке https://www.yellowpages.com/search?search_terms=restaurant&geo_location_terms=Boston.
Затем щелкните правой кнопкой мыши на ссылке страницы и выберите — Проверить элемент. Откроется панель инструментов, показывающая «HTML-содержимое» этой веб-страницы в хорошо структурированном формате.
На этой картинке показаны данные, которые нам нужно спарсить, в теге DIV. Если вы внимательно посмотрите, вы увидите атрибут с именем «class», известный как «result». DIV содержит данные, которые мы должны спарсить.
Давайте найдем HTML-тег(и), в котором содержатся ссылки, которые мы хотим спарсить. Вы можете щелкнуть правой кнопкой мыши на заголовке ссылки в браузере и выполнить «Проверить элемент». Это откроет HTML-содержимое и выделит тег, который содержит данные, на которые вы щелкнули правой кнопкой мыши. См. изображение ниже, чтобы увидеть хорошо структурированные поля данных.
Как настроить компьютер для разработки парсинга веб-страниц?
Для руководства по парсингу веб-страниц мы будем использовать Python 3. Код не будет работать, если вы используете Python 2.7. Для начала вам понадобятся установленные PIP и Python 3 на вашей системе.
Большинство UNIX-подобных операционных систем, включая Mac OS и Linux, поставляются с предустановленным Python. Однако не все Linux-системы по умолчанию поставляются с Python 3.
Чтобы проверить версию Python, просто откройте терминал (в Mac OS и Linux) или командную строку (в Windows) и введите:
python --version
Затем нажмите клавишу Enter. Если вывод выглядит как Python 3.x.x, то у вас установлен Python 3. Аналогично, если это Python 2.x.x, то у вас установлен Python 2. Однако, если выводит ошибки, вероятно, у вас не установлен Python.
Установка Python 3 с помощью Pip
Вы можете использовать этот руководство для установки Python 3 для Linux – http://docs.python-guide.org/en/latest/starting/install3/linux/
Если вы пользователь Mac, вы можете следовать руководству по адресу — http://docs.python-guide.org/en/latest/starting/install3/osx/
Установка пакетов
Используйте Python Requests для выполнения запросов и загрузки HTML-контента с разных страниц по адресу http://docs.python-requests.org/en/master/user/install/.
Используйте Python LXML для разбора древовидной структуры HTML с помощью XPath (Подробнее можно узнать по адресу — http://lxml.de/installation.html))
The Code
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import requests
from lxml import html
import unicodecsv as csv
import argparse
def parse_listing(keyword, place):
"""
Функция для обработки страницы с результатами поиска на Yellow Pages
:param keyword: ключевое слово для поиска
:param place: название места
"""
url = "https://www.yellowpages.com/search?search_terms={0}&geo_location_terms={1}".format(keyword, place)
print("получение ", url)
headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-GB,en;q=0.9,en-US;q=0.8,ml;q=0.7',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': 'www.yellowpages.com',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36'
}
# Добавление повторных попыток
for retry in range(10):
try:
response = requests.get(url, verify=False, headers=headers)
print("разбор страницы")
if response.status_code == 200:
parser = html.fromstring(response.text)
# делаем ссылки абсолютными
base_url = "https://www.yellowpages.com"
parser.make_links_absolute(base_url)
XPATH_LISTINGS = "//div[@class='search-results organic']//div[@class='v-card']"
listings = parser.xpath(XPATH_LISTINGS)
scraped_results = []
for results in listings:
XPATH_BUSINESS_NAME = ".//a[@class='business-name']//text()"
XPATH_BUSSINESS_PAGE = ".//a[@class='business-name']//@href"
XPATH_TELEPHONE = ".//div[@class='phones phone primary']//text()"
XPATH_ADDRESS = ".//div[@class='info']//div//p[@itemprop='address']"
XPATH_STREET = ".//div[@class='street-address']//text()"
XPATH_LOCALITY = ".//div[@class='locality']//text()"
XPATH_REGION = ".//div[@class='info']//div//p[@itemprop='address']//span[@itemprop='addressRegion']//text()"
XPATH_ZIP_CODE = ".//div[@class='info']//div//p[@itemprop='address']//span[@itemprop='postalCode']//text()"
XPATH_RANK = ".//div[@class='info']//h2[@class='n']/text()"
XPATH_CATEGORIES = ".//div[@class='info']//div[contains(@class,'info-section')]//div[@class='categories']//text()"
XPATH_WEBSITE = ".//div[@class='info']//div[contains(@class,'info-section')]//div[@class='links']//a[contains(@class,'website')]/@href"
XPATH_RATING = ".//div[@class='info']//div[contains(@class,'info-section')]//div[contains(@class,'result-rating')]//span//text()"
raw_business_name = results.xpath(XPATH_BUSINESS_NAME)
raw_business_telephone = results.xpath(XPATH_TELEPHONE)
raw_business_page = results.xpath(XPATH_BUSSINESS_PAGE)
raw_categories = results.xpath(XPATH_CATEGORIES)
raw_website = results.xpath(XPATH_WEBSITE)
raw_rating = results.xpath(XPATH_RATING)
# address = results.xpath(XPATH_ADDRESS)
raw_street = results.xpath(XPATH_STREET)
raw_locality = results.xpath(XPATH_LOCALITY)
raw_region = results.xpath(XPATH_REGION)
raw_zip_code = results.xpath(XPATH_ZIP_CODE)
raw_rank = results.xpath(XPATH_RANK)
business_name = ''.join(raw_business_name).strip() if raw_business_name else None
telephone = ''.join(raw_business_telephone).strip() if raw_business_telephone else None
business_page = ''.join(raw_business_page).strip() if raw_business_page else None
rank = ''.join(raw_rank).replace('.\xa0', '') if raw_rank else None
category = ','.join(raw_categories).strip() if raw_categories else None
website = ''.join(raw_website).strip() if raw_website else None
rating = ''.join(raw_rating).replace("(", "").replace(")", "").strip() if raw_rating else None
street = ''.join(raw_street).strip() if raw_street else None
locality = ''.join(raw_locality).replace(',\xa0', '').strip() if raw_locality else None
locality, locality_parts = locality.split(',')
_, region, zipcode = locality_parts.split(' ')
business_details = {
'business_name': business_name,
'telephone': telephone,
'business_page': business_page,
'rank': rank,
'category': category,
'website': website,
'rating': rating,
'street': street,
'locality': locality,
'region': region,
'zipcode': zipcode,
'listing_url': response.url
}
scraped_results.append(business_details)
return scraped_results
elif response.status_code == 404:
print("Не удалось найти местоположение", place)
# нет необходимости повторять для несуществующей страницы
break
else:
print("Не удалось обработать страницу")
return []
except:
print("Не удалось обработать страницу")
return []
if __name__ == "__main__":
argparser = argparse.ArgumentParser()
argparser.add_argument('keyword', help='Ключевое слово для поиска')
argparser.add_argument('place', help='Название места')
args = argparser.parse_args()
keyword = args.keyword
place = args.place
scraped_data = parse_listing(keyword, place)
if scraped_data:
print("Запись полученных данных в %s-%s-yellowpages-scraped-data.csv" % (keyword, place))
with open('%s-%s-yellowpages-scraped-data.csv' % (keyword, place), 'wb') as csvfile:
fieldnames = ['rank', 'business_name', 'telephone', 'business_page', 'category', 'website', 'rating',
'street', 'locality', 'region', 'zipcode', 'listing_url']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, quoting=csv.QUOTE_ALL)
writer.writeheader()
for data in scraped_data:
writer.writerow(data)
Необходимо выполнить весь код, введя имя скрипта, за которым следует -h, в терминале или командной строке:
usage: yellow_pages.py [-h] keyword place
positional arguments:
keyword Ключевое слово для поиска
place Название места
optional arguments:
-h, --help показать это сообщение справки и выйти
Позиционные аргументы ключевое слово представляют собой категорию, а позиционный аргумент место - предпочитаемое место для поиска бизнеса. Давайте рассмотрим пример и получим информацию о бизнесе для ресторанов в Бостоне, МА. Скрипт будет выполнен следующим образом:
python3 yellow_pages.py рестораны Бостон, МА
В папке со скриптом вы должны увидеть файл с названием restaurants-Boston-Yellowpages-scraped-data.csv с извлеченными данными. Давайте рассмотрим некоторую примерную информацию о данных о бизнесе, полученных из YellowPages.com.
Нажмите на следующую ссылку и свяжитесь с нами для получения услуг и бесплатной оценки.
https://www.xbyte.io/contact-us.php
Некоторые ограничения
Этот код должен иметь возможность парсить информацию о бизнесе из большинства местоположений. Однако, если вам нужна профессиональная помощь в парсинге веб-сайтов, не стесняйтесь связаться с нами. Просто заполните данные ниже.