Введение в парсинг веб-страниц с помощью Python

Одна из замечательных особенностей Python – это то, насколько он относительно прост для выполнения довольно сложных и впечатляющих задач. Прекрасный пример этого – парсинг веб-страниц .

Это статья о парсинге веб-страниц с помощью Python. В нем мы рассмотрим основы парсинга веб-страниц с использованием популярных библиотек, таких как requests и beautiful soup.

Темы охватывали:

  • Что такое парсинг веб-страниц?
  • Что такое requests и beautiful soup?
  • Использование селекторов CSS для нацеливания данных на веб-страницу
  • Получение данных о продукте с сайта демонстрационной книги
  • Хранение очищенных данных в форматах CSV и JSON

Что такое веб-скрапинг?

Некоторые веб-сайты могут содержать большое количество ценных данных. Веб-скрапинг означает извлечение данных с веб-сайтов, обычно автоматически с помощью бота или поискового робота. Доступные виды или данные столь же разнообразны, как и сам Интернет. Общие задачи включают

  • анализ цен на акции для информирования об инвестиционных решениях
  • автоматическая загрузка файлов, размещенных на веб-сайтах
  • парсинг данных о контактах компании
  • извлечение данных из локатора магазинов для создания списка офисов
  • сбор данных о товарах с таких сайтов, как Amazon или eBay
  • сбор спортивной статистики для ставок
  • сбор данных для привлечения потенциальных клиентов
  • сопоставление данных, доступных из нескольких источников

Законность парсинга веб-страниц

В прошлом существовала некоторая путаница в отношении законности сбора данных с общедоступных веб-сайтов. Это было несколько прояснено недавно в июле 2020 года в судебном деле, по которому Апелляционный суд США отклонил запросы LinkedIn о запрете аналитической компании HiQ собирать свои данные.

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

Однако действуйте осторожно . Вы всегда должны соблюдать условия сайта, с которого вы хотите собрать данные, а также содержимое его robots.txt файла. Вам также необходимо убедиться, что все данные, которые вы собираете, используются законным образом. Например, вам следует рассмотреть вопросы авторского права и законы о защите данных, такие как GDPR. Также имейте в виду, что решение высшего суда может быть отменено и могут применяться другие законы. Эта статья не предназначена для предоставления юридических консультаций, поэтому, пожалуйста, проведите собственное исследование по этой теме. Можно начать с Quora. Там есть несколько хороших и подробных вопросов и ответов, например, по этой ссылке

Один из способов избежать любых потенциальных юридических препятствий при изучении того, как использовать Python для сбора данных с веб-сайтов, – это использовать сайты, которые либо приветствуют, либо терпят вашу деятельность. Отличное место для начала – парсинг – песочница для парсинга веб-страниц, которую мы будем использовать в этой статье.

Пример веб-скрапинга на Python

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

pip install requests

а также

pip install beautifulsoup4

в командной строке. Для получения подробной информации о том, как устанавливать пакеты в Python, ознакомьтесь с установкой пакетов Python с помощью Pip .

В requests библиотечные способы подключения и извлечения данных из целевой веб-страницы, в то время как beautifulsoup позволяет анализировать и извлекать части тех данных, в которых вы заинтересованы.

Давайте посмотрим на пример:

import csv
import json
import requests
from requests.exceptions import ConnectionError
from bs4 import BeautifulSoup

if __name__ == " __main__":

    url = "http://books.toscrape.com/"

    try:
        request = requests.get(url)
        soup = BeautifulSoup(request.text, "html.parser")
        products = soup.find_all(class_="product_pod")
        data = []
        for product in products:
            title = product.find("h3").text
            price = float(product.find("div", class_="product_price").find("p", class_="price_color").text.strip("£"))
            data.append((title, price))
        store_as_csv(data, headings=["title", "price"])
        store_as_json(data)
        print("### RESULTS ###")
        for item in data:
            print(*item) # Don't let this phase you - it just unpacks the tuples for nicer display.
    except ConnectionError:
        print("Unable to open url.")

Так как же работает код?

Чтобы иметь возможность выполнять парсинг веб-страниц с помощью Python, вам потребуется базовое понимание HTML и CSS . Это сделано для того, чтобы вы понимали территорию, на которой работаете. Вам не нужно быть экспертом, но вам нужно знать, как перемещаться по элементам на веб-странице с помощью инспектора, такого как инструменты Chrome dev . Если у вас нет этих базовых знаний, вы можете пойти и получить их ( w3schools – отличное место для начала), или, если вы чувствуете себя смелым, просто попробуйте следовать и подбирать то, что вам нужно, по ходу дела.

Чтобы увидеть, что происходит в приведенном выше коде, перейдите на http://books.toscrape.com/ . Наведите курсор на цену книги, щелкните правой кнопкой мыши и выберите «проверить» (это вариант в Chrome – это может быть что-то немного другое, например «проверить элемент» в других браузерах. Когда вы это сделаете, появится новая область показывая вам HTML-код, который создал страницу. Вы должны обратить особое внимание на атрибуты «класса» элементов, на которые вы хотите настроить таргетинг.

В нашем коде есть:

products = soup.find_all(class_="product_pod")

При этом используется атрибут class и возвращается список элементов с классом product_pod.

Тогда для каждого из этих элементов у нас есть:

title = product.find("h3").text
price = float(product.find("div", class_="product_price").find("p", class_="price_color").text.strip("£"))

Первая строка довольно проста и просто выбирает текст h3 элемента для текущего продукта. Следующая строка выполняет множество функций и может быть разделена на отдельные строки. По сути, он находит p тег с классом price_color внутри div тега с классом product_price, извлекает текст, удаляет знак фунта и, наконец, преобразует его в число с плавающей запятой. Этот последний шаг не является строго необходимым, поскольку мы будем хранить наши данные в текстовом формате, но я включил его на тот случай, если вам понадобится фактический числовой тип данных в ваших собственных проектах.

Хранение собранных данных в формате CSV

csv (значения, разделенные запятыми) – очень распространенный и полезный формат файлов для хранения данных. Он легкий и не требует базы данных.

Добавьте этот код над if __name__ == " __main__": строкой

def store_as_csv(data, headings=None): # Don't use headings=[] as default argument. It behaves weirdly. if headings is None: headings = []

    with open("data.csv", "w", encoding="utf-8", newline="") as file:
        writer = csv.writer(file)

        # write title row
        writer.writerow(headings)

        # Write data
        for item in data:
            writer.writerow(item)

и непосредственно перед строкой print("### RESULTS ###")добавьте это:

store_as_csv(data, headings=["title", "price"])

Когда вы запустите код, будет создан файл, содержащий данные вашей книги в формате csv. 

title,price
A Light in the ...,51.77
Tipping the Velvet,53.74
Soumission,50.1
Sharp Objects,47.82
Sapiens: A Brief History ...,54.23
...

Хранение собранных данных в формате JSON

Другой очень распространенный формат для хранения данных – это JSON(JavaScript Object Notation), который в основном представляет собой набор списков и словарей (называемых в JavaScript массивами и объектами).

Добавьте этот дополнительный код выше if __name__ == "__main_":

def store_as_json(data):
    # List to store dictionaries containing the data we extracted.
    records = []
    for item in data:
        new_record = {
            "title": item[0],
            "price": item[1]
        }
        records.append(new_record)
    # Write these to a JSON file.
    with open('data.json', 'w') as outfile:
        json.dump(records, outfile, indent=4)

и store_as_json(data) выше print("### Results ###") линии.

[
    {
        "title": "A Light in the ...",
        "price": 51.77
    },
    {
        "title": "Tipping the Velvet",
        "price": 53.74
    },
    {
        "title": "Soumission",
        "price": 50.1
    },
    {
        "title": "Sharp Objects",
        "price": 47.82
    },
    ...
]

Итак, у вас есть это – теперь вы знаете, как собирать данные с веб-страницы, и для этого не потребовалось много строк кода Python!

Полный набор кода для примера веб-скрапинга Python

Вот полный список нашей программы для вашего удобства.

import csv
import json
import requests
from requests.exceptions import ConnectionError
from bs4 import BeautifulSoup

def store_as_csv(data, headings=None): # Don't use headings=[] as default argument. It behaves weirdly.
    if headings is None:
        headings = []

    with open("data.csv", "w", encoding="utf-8", newline="") as file:
        writer = csv.writer(file)

        # write title row
        writer.writerow(headings)

        # Write data
        for item in data:
            writer.writerow(item)

def store_as_json(data):
    # List to store dictionaries containing the data we extracted.
    records = []
    for item in data:
        new_record = {
            "title": item[0],
            "price": item[1]
        }
        records.append(new_record)
    # Write these to a JSON file.
    with open('data.json', 'w') as outfile:
        json.dump(records, outfile, indent=4)

if __name__ == " __main__":

    url = "http://books.toscrape.com/"

    try:
        request = requests.get(url)
        soup = BeautifulSoup(request.text, "html.parser")
        products = soup.find_all(class_="product_pod")
        data = []
        for product in products:
            title = product.find("h3").text
            price = float(product.find("div", class_="product_price").find("p", class_="price_color").text.strip("£"))
            data.append((title, price))
        store_as_csv(data, headings=["title", "price"])
        store_as_json(data)
        print("### RESULTS ###")
        for item in data:
            print(*item) # Don't let this phase you - it just unpacks the tuples for nicer display.
    except ConnectionError:
        print("Unable to open url.")

И последнее замечание. Мы использовали requests и beautifulsoup для нашего парсинга, и большая часть существующего кода в Интернете в статьях и репозиториях использует эти библиотеки. Однако есть более новая библиотека, которая выполняет обе задачи вместе, и имеет некоторые дополнительные функции, которые могут оказаться полезными позже. Эту новую библиотеку requests-HTML стоит посмотреть сразу после того, как вы получите базовое представление о том, чего вы пытаетесь достичь с помощью парсинга веб-страниц. Еще одна библиотека, которая часто используется для более сложных проектов, охватывающих несколько страниц, – это scrapy, но в целом, более сложный зверь, для более поздних статей.

Работа с содержанием этой статьи даст вам прочную основу в основах парсинга веб-страниц в Python. Я надеюсь ты сочтёшь это полезным

Удачных вычислений.

Ответить