CoderCastrov logo
CoderCastrov
Парсер данных

Как парсить Yellow Pages с помощью Python и LXML?

Как парсить Yellow Pages с помощью Python и LXML?
просмотров
6 мин чтение
#Парсер данных

В этом учебнике по парсингу мы рассмотрим, как парсить YellowPages.com с помощью Python и LXML, чтобы получить информацию о бизнесе на основе категории и города из Yellow Pages.

Чтобы использовать этот парсер Yellow Pages, давайте пройдемся по страницам Yellow Pages с данными о разных ресторанах в городе. Затем извлечем информацию о бизнесе из результатов первой страницы.

Какие данные мы извлекаем?

Вот поля данных, которые мы будем парсить:

  • Рейтинги
  • Название бизнеса
  • Страницы бизнеса
  • Номера телефонов
  • Веб-сайт
  • Название улицы
  • Категория
  • Рейтинги
  • Регион
  • Местоположение
  • URL
  • Почтовый индекс

Вот скриншот информации, которую мы будем парсить с Yellow Pages с использованием API Yellow Pages.

Как найти данные?

Сначала нам нужно найти данные, которые доступны на текущей странице в HTML-тегах, прежде чем начать создавать парсер Yellow Pages. Для этого вам следует понять HTML-теги содержимого страницы.

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

Давайте рассмотрим HTML-код веб-страницы и узнаем, где находятся данные. Мы собираемся сделать следующее:

  1. Получить HTML-теги, которые содержат список ссылок, откуда мы хотим получить данные.

  2. Получить ссылки из этого списка и извлечь данные.

HTML Tags

Обзор 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

Некоторые ограничения

Этот код должен иметь возможность парсить информацию о бизнесе из большинства местоположений. Однако, если вам нужна профессиональная помощь в парсинге веб-сайтов, не стесняйтесь связаться с нами. Просто заполните данные ниже.


Источник