Перейти к содержимому

Как получить ссылку из тега python

  • автор:

Извлечение всех ссылок web-сайта с помощью Python

Одна из задач, которая стояла в рамках проекта, нацеленного на исследование мер поисковой оптимизации (SEO, search engine optimization) информационных ресурсов дочерних структур организации, предполагала поиск всех ссылок и выявление среди них так называемых «мертвых (битых) ссылок», отсылающих на несуществующий сайт, страницу, файл, что в свою очередь понижает рейтинг информационного ресурса.

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

Посмотрим, как можно создать инструмент извлечения ссылок в Python, используя пакет requests и библиотеку BeautifulSoup. Итак,

pip install requests bs4

Импортируем необходимые модули:

import requests from urllib.parse import urlparse, urljoin from bs4 import BeautifulSoup

Затем определим две переменные: одну для всех внутренних ссылок (это URL, которые ссылаются на другие страницы того же сайта), другую для внешних ссылок вэб-сайта (это ссылки на другие сайты).

# Инициализировать набор ссылок (уникальные ссылки) int_url = set() ext_url = set()

Далее создадим функцию для проверки URL – адресов. Это обеспечит правильную схему в ссылке — протокол, например, http или https и имя домена в URL.

# Проверяем URL def valid_url(url): parsed = urlparse(url) return bool(parsed.netloc) and bool(parsed.scheme)

На следующем шаге создадим функцию, возвращающую все действительные URL-адреса одной конкретной веб-страницы:

# Возвращаем все URL-адреса def website_links(url): urls = set() # извлекаем доменное имя из URL domain_name = urlparse(url).netloc # скачиваем HTML-контент вэб-страницы soup = BeautifulSoup(requests.get(url).content, "html.parser")

Теперь получим все HTML теги, содержащие все ссылки вэб-страницы.

 for a_tag in soup.findAll("a"): href = a_tag.attrs.get("href") if href == "" or href is None: # href пустой тег continue

В итоге получаем атрибут href и проверяем его. Так как не все ссылки абсолютные, возникает необходимость выполнить соединение относительных URL-адресов и имени домена. К примеру, когда найден href — «/search» и URL — «google.com» , то в результате получим «google.com/search».

# присоединить URL, если он относительный (не абсолютная ссылка) href = urljoin(url, href)

В следующем шаге удаляем параметры HTTP GET из URL-адресов:

parsed_href = urlparse(href) # удалить параметры URL GET, фрагменты URL и т. д. href = parsed_href.scheme + "://" + parsed_href.netloc + parsed_href.path 

Если URL-адрес недействителен/URL уже находится в int_url , следует перейти к следующей ссылке.

Если URL является внешней ссылкой, вывести его и добавить в глобальный набор ext_url и перейдти к следующей ссылке.

И наконец, после всех проверок получаем URL, являющийся внутренней ссылкой; выводим ее и добавляем в наборы urls и int_url

 if not valid_url(href): # недействительный URL continue if href in int_url: # уже в наборе continue if domain_name not in href: # внешняя ссылка if href not in ext_url: print(f"[!] External link: ") ext_url.add(href) continue print(f"[*] Internal link: ") urls.add(href) int_url.add(href) return urls 

Напоминаю, что эта функция захватывает ссылки одной вэб-страницы.

Теперь создадим функцию, которая сканирует весь веб-сайт. Данная функция получает все ссылки на первой странице сайта, затем рекурсивно вызывается для перехода по всем извлеченным ссылкам. Параметр max_urls позволяет избежать зависания программы на больших сайтах при достижении определенного количества проверенных URL-адресов.

# Количество посещенных URL-адресов visited_urls = 0 # Просматриваем веб-страницу и извлекаем все ссылки. def crawl(url, max_urls=50): # max_urls (int): количество макс. URL для сканирования global visited_urls visited_urls += 1 links = website_links(url) for link in links: if visited_urls > max_urls: break crawl(link, max_urls=max_urls) 

Итак, проверим на сайте, к которому имеется разрешение, как все это работает:

if __name__ == "__main__": crawl("https://newtechaudit.ru") print("[+] Total External links:", len(ext_url)) print("[+] Total Internal links:", len(int_url)) print("[+] Total:", len(ext_url) + len(int_url))

Вот фрагмент результата работы программы:

Обратите внимание, что многократный запрос к одному и тому же сайту за короткий промежуток времени может привести к тому, что ваш IP-адрес будет заблокирован. Ссылка на оригинал поста.

Модуль BeautifulSoup4 в Python, разбор HTML

BeautifulSoup4 (bs4) — это библиотека Python для извлечения данных из файлов HTML и XML. Для естественной навигации, поиска и изменения дерева HTML, модуль BeautifulSoup4, по умолчанию использует встроенный в Python парсер html.parser . BS4 так же поддерживает ряд сторонних парсеров Python, таких как lxml , html5lib и xml (для разбора XML-документов).

Установка BeautifulSoup4 в виртуальное окружение:

# создаем виртуальное окружение, если нет $ python3 -m venv .venv --prompt VirtualEnv # активируем виртуальное окружение $ source .venv/bin/activate # ставим модуль beautifulsoup4 (VirtualEnv):~$ python3 -m pip install -U beautifulsoup4

Содержание:

  • Выбор парсера для использования в BeautifulSoup4.
    • Парсер lxml .
    • Парсер html5lib .
    • Встроенный в Python парсер html.parser .
    • Навигация по структуре HTML-документа.
    • Извлечение URL-адресов.
    • Извлечение текста HTML-страницы.
    • Поиск тегов по HTML-документу.
    • Поиск тегов при помощи CSS селекторов.
    • Дочерние элементы.
    • Родительские элементы.
    • Изменение имен тегов HTML-документа.
    • Добавление новых тегов в HTML-документ.
    • Удаление и замена тегов в HTML-документе.
    • Изменение атрибутов тегов HTML-документа.

    Выбор парсера для использования в BeautifulSoup4.

    BeautifulSoup4 представляет один интерфейс для разных парсеров, но парсеры неодинаковы. Разные парсеры, анализируя один и того же документ создадут различные деревья HTML. Самые большие различия будут между парсерами HTML и XML. Так же парсеры различаются скоростью разбора HTML документа.

    Если дать BeautifulSoup4 идеально оформленный документ HTML, то различий построенного HTML-дерева не будет. Один парсер будет быстрее другого, но все они будут давать структуру, которая выглядит точно так же, как оригинальный документ HTML. Но если документ оформлен с ошибками, то различные парсеры дадут разные результаты.

    Различия в построении HTML-дерева разными парсерами, разберем на короткой HTML-разметке: .

    Парсер lxml .
    • Для запуска примера, необходимо установить модуль lxml .
    • Очень быстрый, имеет внешнюю зависимость от языка C.
    • Нестрогий.
    >>> from bs4 import BeautifulSoup >>> BeautifulSoup(" ", "lxml") # 

    Обратите внимание, что тег заключен в теги и , а висячий тег

    просто игнорируется.

    Парсер html5lib .
    • Для запуска примера, необходимо установить модуль html5lib .
    • Ну очень медленный.
    • Разбирает страницы так же, как это делает браузер, создавая валидный HTML5.
    >>> from bs4 import BeautifulSoup >>> BeautifulSoup(" ", "html5lib") # 

    Обратите внимание, что парсер html5lib НЕ игнорирует висячий тег

    , и к тому же добавляет открывающий тег

    . Также html5lib добавляет пустой тег ( lxml этого не сделал).

    Встроенный в Python парсер html.parser .
    • Не требует дополнительной установки.
    • Приличная скорость, но не такой быстрый, как lxml .
    • Более строгий, чем html5lib .
    >>> from bs4 import BeautifulSoup >>> BeautifulSoup(" ", 'html.parser') # 

    Как и lxml , встроенный в Python парсер игнорирует закрывающий тег

    . В отличие от html5lib , этот парсер не делает попытки создать правильно оформленный HTML-документ, добавив теги или .

    Вывод: Парсер html5lib использует способы, которые являются частью стандарта HTML5, поэтому он может претендовать на то, что его подход самый «правильный«.

    Основные приемы работы с BeautifulSoup4.

    Чтобы разобрать HTML-документ, необходимо передать его в конструктор класса BeautifulSoup() . Можно передать строку или открытый дескриптор файла:

    from bs4 import BeautifulSoup # передаем объект открытого файла with open("index.html") as fp: soup = BeautifulSoup(fp, 'html.parser') # передаем строку soup = BeautifulSoup("a web page", 'html.parser') 

    Первым делом документ конвертируется в Unicode, а HTML-мнемоники конвертируются в символы Unicode:

    >>> from bs4 import BeautifulSoup >>> html = " Sacré bleu!" >>> parse = BeautifulSoup(html, 'html.parser') >>> print(parse) # Sacré bleu! 

    Дальнейшие примеры будут разбираться на следующей HTML-разметке.

    html_doc = """html>head>title>The Dormouse's storytitle>head> body> p class="title">b>The Dormouse's storyb>p> p class="story">Once upon a time there were three little sisters; and their names were a href="http://example.com/elsie" class="sister" id="link1">Elsiea>, a href="http://example.com/lacie" class="sister" id="link2">Laciea> and a href="http://example.com/tillie" class="sister" id="link3">Tilliea>; and they lived at the bottom of a well.p> p class="story">. p>"""

    Передача этого HTML-документа в конструктор класса BeautifulSoup() создает объект, который представляет документ в виде вложенной структуры:

    >>> from bs4 import BeautifulSoup >>> soup = BeautifulSoup(html_doc, 'html.parser') >>> print(soup.prettify()) # # # # The Dormouse's story #  #  # # 

    # # The Dormouse's story # #

    #

    # Once upon a time there were three little sisters; and their names were # # Elsie # # , # # Lacie # # and # # Tillie # # ; and they lived at the bottom of a well. #

    #

    # . #

    # #

    Навигация по структуре HTML-документа:

    # извлечение тега `title` >>> soup.title # The Dormouse's story # извлечение имя тега >>> soup.title.name # 'title' # извлечение текста тега >>> soup.title.string # 'The Dormouse's story' # извлечение первого тега `

    ` >>> soup.p #

    # извлечение второго тега `

    ` и # представление его содержимого списком >>> soup.find_all('p')[1].contents # ['Once upon a time there were three little sisters; and their names were\n', # # ',\n', # # ' and\n', # # ';\nand they lived at the bottom of a well.'] # выдаст то же самое, только в виде генератора >>> soup.find_all('p')[1].strings #

    Перемещаться по одному уровню можно при помощи атрибутов .previous_sibling и .next_sibling . Например, в представленном выше HTML, теги обернуты в тег

    — следовательно они находятся на одном уровне.

    >>> first_a = soup.a >>> first_a # >>> first_a.previous_sibling # 'Once upon a time there were three little sisters; and their names were\n' >>> next = first_a.next_sibling >>> next # ',\n' >>> next.next_sibling # Так же можно перебрать одноуровневые элементы данного тега с помощью .next_siblings или .previous_siblings .
    for sibling in soup.a.next_siblings: print(repr(sibling)) # ',\n' # # ' and\n' # # '; and they lived at the bottom of a well.' for sibling in soup.find(id="link3").previous_siblings: print(repr(sibling)) # ' and\n' # # ',\n' # # 'Once upon a time there were three little sisters; and their names were\n' 

    Атрибут .next_element строки или HTML-тега указывает на то, что было разобрано непосредственно после него. Это могло бы быть тем же, что и .next_sibling , но обычно результат резко отличается.

    last_a = soup.find("a", id="link3") last_a # last_a.next_sibling # ';\nand they lived at the bottom of a well.' 
    last_a_tag.next_element # 'Tillie' 

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

    Атрибут .previous_element является полной противоположностью .next_element . Он указывает на элемент, который был обнаружен при разборе непосредственно перед текущим:

    last_a_tag.previous_element # ' and\n' last_a_tag.previous_element.next_element # При помощи атрибутов .next_elements и .previous_elements можно получить список элементов, в том порядке, в каком он был разобран парсером.
    for element in last_a_tag.next_elements: print(repr(element)) # 'Tillie' # ';\nand they lived at the bottom of a well.' # '\n' # # '. ' # '\n' 

    Извлечение URL-адресов.

    Одна из распространенных задач, это извлечение URL-адресов, найденных на странице в HTML-тегах :

    >>> for a in soup.find_all('a'): . print(a.get('href')) # http://example.com/elsie # http://example.com/lacie # http://example.com/tillie 

    Извлечение текста HTML-страницы.

    Другая распространенная задача — извлечь весь текст со HTML-страницы:

    # Весь текст HTML-страницы с разделителями `\n` >>> soup.get_text('\n', strip='True') # "The Dormouse's story\nThe Dormouse's story\n # Once upon a time there were three little sisters; and their names were\n # Elsie\n,\nLacie\nand\nTillie\n;\nand they lived at the bottom of a well.\n. " # а можно создать список строк, а потом форматировать как надо >>> [text for text in soup.stripped_strings] # ["The Dormouse's story", # "The Dormouse's story", # 'Once upon a time there were three little sisters; and their names were', # 'Elsie', # ',', # 'Lacie', # 'and', # 'Tillie', # ';\nand they lived at the bottom of a well.', # '. '] 

    Поиск тегов по HTML-документу:

    Найти первый совпавший HTML-тег можно методом BeautifulSoup.find() , а всех совпавших элементов — BeautifulSoup.find_all() .

    # ищет все теги ``</span> <span >>>></span> <span >soup</span><span >.</span><span >find_all</span><span >(</span><span >"title"</span><span >)</span> <span ># [<title>The Dormouse's story] # ищет все теги `` и все теги `` >>> soup.find_all(["a", "b"]) # [The Dormouse's story, # # # # ищет все теги `

    ` с CSS классом "title" >>> soup.find_all("p", "title") # [

    ]
    # ищет все теги с CSS классом, в именах которых встречается "itl" soup.find_all(class_=re.compile("itl")) # [

    ]
    # ищет все теги с >>>> soup.find_all(id="link2") # [# ищет все теги ``, содержащие указанные атрибуты >>> soup.find_all('a', attrs='class': 'sister', 'id': 'link1'>) # [# ищет текст внутри всех тегов, который содержит 'sisters' >>> import re >>> soup.find(string=re.compile("sisters")) # 'Once upon a time there were three little sisters; and their names were\n' # ищет все теги, имена которых начинаются на букву 'b' for tag in soup.find_all(re.compile("^b")): print(tag.name) # body # b # ищет все теги в документе, но не текстовые строки for tag in soup.find_all(True): print(tag.name) # html # head # title # body # p # b # p # a # a # a # p

    Поиск тегов при помощи CSS селекторов:

    >>> soup.select("title") # [The Dormouse's story] >>> soup.select("p:nth-of-type(3)") # [Поиск тега под другими тегами:
    >>> soup.select("body a") # [# # >>> soup.select("html head title") # [The Dormouse's story] 

    Поиск тега непосредственно под другими тегами:

    >>> soup.select("head > title") # [The Dormouse's story] >>> soup.select("p > a:nth-of-type(2)") # [>>> soup.select("p > #link1") # [Поиск одноуровневых элементов:
    # поиск всех `.sister` в которых нет `#link1` >>> soup.select("#link1 ~ .sister") # [# # поиск всех `.sister` в которых есть `#link1` >>> soup.select("#link1 + .sister") # [# поиск всех `` у которых есть сосед `

    `

    Поиск тега по классу CSS:

    >>> soup.select(".sister") # [# # Поиск тега по ID:
    >>> soup.select("#link1") # [>>> soup.select("a#link2") # [ 

    Дочерние элементы.

      будут являться три тега
      и тег

        со всеми вложенными тегами.

      Обратите внимание, что все переводы строк \n и пробелы между тегами, так же будут считаться дочерними элементами. Так что имеет смысл заранее привести исходный HTML к «нормальному виду«, например так: re.sub(r’>\s+

      Извлечение ВСЕХ дочерних элементов. Эта операция похожа на рекурсивный обход HTML-дерева в глубину от выбранного тега.

      Обратите внимание, что простой текст, который находится внутри тега, так же считается дочерним элементом этого тега.

      Если внутри тега есть более одного дочернего элемента (как в примерен выше) и необходимо извлечь только текст, то можно использовать атрибут .strings или генератор .stripped_strings .

      Генератор .stripped_strings дополнительно удаляет все переводы строк \n и пробелы между тегами в исходном HTML-документе.

      >>> list(first_ul.strings) # ['текст 1', 'текст 2', 'текст 2-1', 'текст 2-2', 'текст 3'] >>> first_ul.stripped_strings # >>> list(first_ul.stripped_strings) # ['текст 1', 'текст 2', 'текст 2-1', 'текст 2-2', 'текст 3'] 

      Родительские элементы.

      Что бы получить доступ к родительскому элементу, необходимо использовать атрибут .parent .

      Taк же можно перебрать всех родителей элемента с помощью атрибута .parents .

      Изменение имен тегов HTML-документа:

      >>> soup = BeautifulSoup('

      '
      , 'html.parser') >>> tag = soup.b # присваиваем новое имя тегу >>> tag.name = "blockquote" >>> tag #
      >>> soup #

      Изменение HTML-тега

      на тег :

      >>> soup = BeautifulSoup('

      Extremely bold

      '
      , 'html.parser') >>> soup.p.name = 'div' >>> soup #
      Extremely bold

      Добавление новых тегов в HTML-документ.

      Добавление нового тега в дерево HTML:

      Добавление новых тегов до/после определенного тега или внутрь тега.

      >>> soup = BeautifulSoup("

      leave

      "
      , 'html.parser') >>> tag = soup.new_tag("i", id='new') >>> tag.string = "Don't" # добавление нового тега до тега >>> soup.b.insert_before(tag) >>> soup.b #

      Don'tleave

      # добавление нового тега после тега >>> soup.b.insert_after(tag) >>> soup #

      leaveDon't

      # добавление нового тега внутрь тега >>> soup.b.string.insert_before(tag) >>> soup.b #

      Don'tleave

      Удаление и замена тегов в HTML-документе.

      Удаляем тег или строку из дерева HTML:

      >>> html = 'I linked to example.com' >>> soup = BeautifulSoup(html, 'html.parser') >>> a_tag = soup.a # удаляем HTML-тег `` с сохранением # в переменной `i_tag` >>> i_tag = soup.i.extract() # смотрим что получилось >>> a_tag # I linked to >>> i_tag # example.com 

      Заменяем тег и/или строку в дереве HTML:

      >>> html = 'I linked to example' >>> soup = BeautifulSoup(html, 'html.parser') >>> a_tag = soup.a # создаем новый HTML тег >>> new_tag = soup.new_tag("b") >>> new_tag.string = "sample" # производим замену тега `` внутри тега `` >>> a_tag.i.replace_with(new_tag) >>> a_tag # I linked to sample 

      Изменение атрибутов тегов HTML-документа.

      У тега может быть любое количество атрибутов. Тег имеет атрибут id , значение которого равно boldest . Доступ к атрибутам тега можно получить, обращаясь с тегом как со словарем:

      >>> soup = BeautifulSoup('

      , 'html.parser') >>> tag = soup.b >>> tag['id'] # 'boldest' # доступ к словарю с атрибутами >>> tag.attrs #

      Можно добавлять и изменять атрибуты тега.

      # изменяем `id` >>> tag['id'] = 'bold' # добавляем несколько значений в `class` >>> tag['class'] = ['new', 'bold'] # или >>> tag['class'] = 'new bold' >>> tag # А так же производить их удаление.
      >>> del tag['id'] >>> del tag['class'] >>> tag # bolder >>> tag.get('id') # None 
      • КРАТКИЙ ОБЗОР МАТЕРИАЛА.
      • Основной объект Tag() модуля BeautifulSoup4
      • Методы .find_all() и .find*() модуля BeautifulSoup4
      • CSS селекторы и модуль BeautifulSoup4
      • Метод .get_text() модуля BeautifulSoup4
      • Разбор части документа в BeautifulSoup4 Python
      • Ошибки при чтении и разборе HTML модулем BeautifulSoup4

      Как использовать библиотеку BeautifulSoup4 в Python

      Веб парсинг – это процесс автоматического извлечения данных со страниц сайтов, при котором используются специальные программы. Он основан на анализе HTML-кода страницы и извлечении нужной информации для дальнейшего использования. Веб парсинг позволяет получать текст, изображения, ссылки и другую информацию, размещенную на веб-странице. Также этот процесс называют веб-скрейпинг, от английского слова “scraping” – “соскоб”.

      Для веб-парсинга используются специализированные инструменты и программы, которые могут анализировать HTML-код страницы, извлекать нужные данные и сохранять их в структурированном формате, например, в базе данных или Excel-таблице.

      Веб парсинг может подойти для различных целей: сбор данных для анализа рынка, мониторинг цен на товары, сбор информации о конкурентах, автоматическое обновление содержимого веб-сайтов. Эта технология широко применяется в таких областях как, маркетинг, аналитика, исследование рынка, а также для автоматизации рутинных задач в интернете.

      Парсинг может быть невозможен при наличии правовых ограничений, автоматических систем защиты от парсинга (например, CAPTCHA) или изменений в структуре HTML-кода страницы.

      Что такое библиотека BeautifulSoup

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

      Преимущества BeautifulSoup:

      • Простота использования. Простой и понятный интерфейс для парсинга и навигации по документам.
      • Гибкость. Библиотека поддерживает различные методы поиска, фильтрации и манипуляции с данными, что позволяет легко осуществлять различные операции с HTML и XML документами.
      • Поддержка сложных структур помогает обрабатывать и извлекать данные из таких объектов, как например, вложенные теги и структуры документов.

      Для работы с большими массивами данных предлагаем использовать услугу Аренда выделенного сервера. Надежно защищенное оборудование показывает высокую производительность и низкий процент отказа.

      Какие задачи можно решить с помощью BeautifulSoup

      1. Извлечение данных. BeautifulSoup позволяет извлекать тексты, атрибуты, ссылки и другие данные из HTML/XML документов. Например, вы можете извлечь заголовки новостей с веб-страницы или данные из таблицы.
      2. Фильтрация данных на основе тегов, классов, идентификаторов, атрибутов и других характеристик элементов. Например, вы можете найти все ссылки или изображения на странице с определенным классом или атрибутом.
      3. BeautifulSoup предоставляет методы для навигации по иерархической структуре HTML и XML документов. Например, вы можете найти все дочерние элементы определенного объекта или найти родительский элемент для данного объекта.
      4. Библиотека позволяет добавлять, изменять и удалять элементы в документе. Например, вы можете создать новый элемент и добавить его в определенное место на странице или изменить содержимое существующего элемента.
      5. Очистка данных от HTML/XML тегов и сущностей. Например, вы можете удалить все теги и получить только текстовое содержимое страницы.
      6. BeautifulSoup может быть использована для сбора данных с веб-страниц. Например, вы можете автоматически собирать информацию о товарах онлайн-магазина или получить информацию о погоде с сайта погоды.
      7. BeautifulSoup может быть использована для тестирования и проверки структуры HTML/XML документов. Например, вы можете проверить наличие определенных тегов или атрибутов на странице.

      Пример использования библиотеки Beautifulsoup в Python

      Перед началом работы с библиотекой выполните ее установку с помощью команды:

      from bs4 import BeautifulSoup

      Также загрузите библиотеку requests, с помощью которой можно делать запрос на нужный сайт:

      Чтобы загрузить нужную вам HTML-страницу, выполните:

      Для создания объекта BeautifulSoup:

      soup = BeautifulSoup(html, ‘html.parser’)

      Примеры запросов с использованием библиотеки BeautifulSoup:

      • Найти все теги на странице и вывести их содержимое:

      for link in links:

      • Найти элемент с определенным идентификатором и вывести его содержимое:
      • Найти элементы по атрибутам и их значениям:

      elements = soup.find_all(attrs={‘data-name’: ‘my-data’})

      for element in elements:

      • Создать новый элемент:

      new_element.string = ‘New paragraph’

      • Добавить новый элемент в документ
      • Изменить содержимое элемента:

      element.string = ‘New heading’

      • Удалить элемент:
      • Получить HTML код документа:

      Заключение

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

      Благодаря своей простоте и гибкости, BeautifulSoup является популярным инструментом для веб-скрапинга и анализа данных. Она позволяет разработчикам легко извлекать информацию с веб-страниц и использовать ее для различных целей, таких как парсинг новостей, получение данных с целевых сайтов или анализ HTML-кода.

      Туториал по библиотеке BeautifulSoup4

      Парсеры — это программы, которые скачивают из интернета странички и разбирают их на составляющие: заголовок, картинка, текст… С помощью него можно выкачать с сайта гигабайты полезной информации. Библиотека BeautifulSoup4 как раз предназначена для парсинга.

      В этой статье вы узнаете как распарсить сайт Франка Сонненберга. Цель: по ссылке на пост вытащить его название, текст и картинку.

      Франк Сонненберг — известный американский писатель и коуч. За свои книги он попал в “Топ 100 Американских мыслителей”, а его блог принадлежит списку “Лучшие блоги о лидерстве 21 века”.

      Прежде чем начинать…

      Для прохождения этого туториала вам понадобятся 3 библиотеки:

      $ pip install requests BeautifulSoup4 lxml 

      Получить страничку поста

      Будем парсить пост “Are You Grateful?”. Чтобы распарсить HTML-страничку с постом, сначала нужно её скачать. Это можно сделать с помощью requests , вот статья об этой библиотеке.

      import requests url = 'https://www.franksonnenbergonline.com/blog/are-you-grateful/' response = requests.get(url) response.raise_for_status() print(response.text) 

      Здесь мы просто сделали запрос по ссылке и получили в ответ огромный HTML. Начинаться он будет примерно так:

      DOCTYPE html> html lang="en-US"> head > meta charset="UTF-8" /> meta name="viewport" content="width=device-width, initial-scale=1" /> . 

      Парсинг поста

      У вас есть HTML страничка, но как достать оттуда заголовок поста, картинку и текст? Наконец, на сцену выходит BeautifulSoup. Сейчас вы получили HTML из response.text , но это просто строка с HTML кодом. Для работы с библиотекой BeautifulSoup нужно сделать из этой строки HTML-суп:

      from bs4 import BeautifulSoup soup = BeautifulSoup(response.text, 'lxml') print(soup.prettify()) 

      В Python-коде суп — это новый объект с кучей возможностей. Например, теперь можно вывести HTML красиво, с отступами, с помощью метода soup.prettify() :

      DOCTYPE html> html lang="en-US"> head> meta charset="utf-8"/> meta content="width=device-width, initial-scale=1" name="viewport"/> title> Are You Grateful? . 

      Супом он называется исторически, вот статья об этом термине. Если вкратце, то на самом деле верстальщики иногда косячат и, например, забывают закрывать теги или оставляют какие-нибудь неисправности. Такой код на HTML стали называть tag soup . Браузеры умеют самостоятельно исправлять какие-то огрехи и делать из такого “супа” нормальный, рабочий HTML. Но если вы скачиваете страничку через requests , то браузер тут ни при чём, и вы получите такой HTML, какой написали верстальщики сайта, со всеми его ошибками.

      Для этого и нужна библиотека lxml , она подправит мелкие недочёты, и с ней BeautifulSoup справится даже с очень плохой вёрсткой. В этой строчке вы как раз говорите библиотеке BeautifulSoup использовать lxml :

      soup = BeautifulSoup(response.text, 'lxml') 

      Заголовок поста

      Заголовок поста можно легко найти методом супа .find() . Для начала нужно узнать в какой тег этот заголовок обёрнут. В этом помогут инструменты разработчика:

      Итак, тег h1 . Вот что вернёт метод .find() :

      print(soup.find('h1')) # 

      Это тоже суп, но уже не со всей HTML-страницей, а только с этим тегом и тегами внутри него. Заголовка поста тут нет: пост называется Are You Grateful? , а такого текста в этом теге нет. Похоже, что это не тот тег , который вы искали. Их на странице несколько и BeautifulSoup4 выдал первый, который нашёл. Это тег , который находится в самом верху страницы:

      Как же найти заголовок поста, а не страницы? Можно уточнить запрос: заголовок поста лежит в теге , а тот — в :

      Давайте попробуем такой запрос:

      title_tag = soup.find('main').find('header').find('h1') print(title_tag) # 

      Are You Grateful?

      Тег нашли, а как достать его текст? Всё очень просто:

      title_tag = soup.find('main').find('header').find('h1') title_text = title_tag.text print(title_text) # Are You Grateful? 

      Победа, вы добрались до заголовка поста!

      Картинка поста

      Картинку можно найти так же: это единственный тег внутри тега . Но давайте попробуем другой подход, найдём её по классу. У картинки есть классы:

      У картинки есть 3 класса, они перечислены через пробел:

      attachment-post-image size-post-image wp-post-image 

      Класс attachment-post-image переводится как “Картинка поста”, а значит наверняка он есть только у картинок поста. Вот как найти тег img , у которого есть такой класс:

      soup.find('img', class_='attachment-post-image') # # fortunate, things to be grateful for, why you should be grateful, Frank Sonnenberg" class token comment"># size-post-image wp-post-image" height="400" sizes="(max-width: 800px) 100vw, 800px" # src="https://www.franksonnenbergonline.com/wp-content/uploads/2019/10/image_are-you-grateful.jpg" ... 

      Тот же .find() , только указали параметр class_ . Нижнее подчёркивание разработчики библиотеки добавили для того, чтобы не было пересечения со словом class из Python, которое используется для создания классов.

      Осталось достать адрес картинки, он лежит в аргументе src :

      soup.find('img', class_='attachment-post-image')['src'] # https://www.franksonnenbergonline.com/wp-content/uploads/2019/10/image_are-you-grateful.jpg 

      Домашнее задание

      Осталось спарсить текст поста. Сделать это можно одним из способов выше: по классу или тегам, с помощью метода find .

      Попробуйте бесплатные уроки по Python

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

      Переходите на страницу учебных модулей «Девмана» и выбирайте тему.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *