BeautifulSoup – парсинг HTML в Python на примерах

Работа с веб-страницами не ограничивается одним лишь их созданием или открытием. Например, может понадобиться открыть на них какую-то информацию. Сегодня поговорим о том, как использовать библиотеку BeautifulSoup Python. В частности, разберемся, как с ее помощью использовать те или иные теги, модифицировать документы, осуществлять перебор его элементов, а также как выполнять парсинг веб-страниц.

Примеры BeautifulSoup

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

Как установить BeautifulSoup в Python

Чтобы установить подходящие модули, необходимо воспользоваться командой pip3

$ sudo pip3 install lxml

Сперва понадобится выполнить инсталляцию lxml модуля, который будет использоваться в BeautifulSoup. 

$ sudo pip3 install bs4

Собственно, эта команда и используется для установки пакета.

Пример кода HTML-страницы

Дальше мы будем работать со следующим документом. 

<!DOCTYPE html>

<html>

    <head>

        <title>Header</title>

        <meta charset="utf-8">                   

    </head>

        

    <body>

        <h2>Operating systems</h2>

        

        <ul id="mylist" style="width:150px">

            <li>Solaris</li>

            <li>FreeBSD</li>

            <li>Debian</li>                      

            <li>NetBSD</li>           

            <li>Windows</li>         

        </ul>

        

        <p>

          FreeBSD is an advanced computer operating system used to 

          power modern servers, desktops, and embedded platforms.

        </p>

                

        <p>

          Debian is a Unix-like computer operating system that is 

          composed entirely of free software.

        </p>        

        

    </body>    

</html>

Простой пример парсинга HTML с использованием BeautifulSoup

В первом примере будет применяться BeautifulSoup модуль для получения трех тегов. 

#!/usr/bin/python3




from bs4 import BeautifulSoup




with open("index.html", "r") as f:

    

    contents = f.read()




    soup = BeautifulSoup(contents, 'lxml')




    print(soup.h2)

    print(soup.head)

    print(soup.li)

С помощью приведенного в этом примере кода можно вывести HTML-код трех тегов. 

from bs4 import BeautifulSoup

А здесь мы импортировали класс BeautifulSoup из модуля bs4. Следовательно, BeautifulSoup здесь является главным классом. 

with open("index.html", "r") as f:

    

    contents = f.read()

Откроется файл index.html, после чего его содержимое будет прочитано с использованием метода read().  

soup = BeautifulSoup(contents, 'lxml')

Эта строка кода создаст объект BeautifulSoup. Данные будут переданы конструктору. А с помощью второй опции уточняется объект парсинга. 

print(soup.h2)

print(soup.head)

Затем осуществляется вывод HTML-кода тегов h2 и head,

print(soup.li)

В этом примере многократно используются элементы li, но выводится лишь только первый из них. 

$ ./simple.py 

<h2>Operating systems</h2>

<head>

<title>Header</title>

<meta charset="utf-8"/>

</head>

<li>Solaris</li>

Этот фрагмент – результат вывода.

Теги, атрибуты name и text

С помощью атрибута name мы получаем название тега, а атрибута text – его содержимое. 

#!/usr/bin/python3




from bs4 import BeautifulSoup




with open("index.html", "r") as f:

    

    contents = f.read()




    soup = BeautifulSoup(contents, 'lxml')




    print("HTML: {0}, name: {1}, text: {2}".format(soup.h2, 

        soup.h2.name, soup.h2.text))

Код в примере дает возможность вывести HTML-код, название и текст h2 тега. 

$ ./tags_names.py 

HTML: <h2>Operating systems</h2>, name: h2, text: Operating systems

Этот результат будет отображен в процессе вывода.

BeautifulSoup – перебор тегов HTML

Чтобы выполнить перебор содержимого HTML-документа, используется метод recursiveChildGenerator(). Работает он следующим образом. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

            

    for child in soup.recursiveChildGenerator():

        

        if child.name:

            

            print(child.name)

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

$ ./traverse_tree.py 

html

head

title

meta

body

h2

ul

li

li

li

li

li

p

p

Эти теги являются составляющими рассматриваемого документа HTML.

BeautifulSoup – использование атрибута children

С помощью атрибута children можно вывести все дочерние теги. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    root = soup.html

    

    root_childs = [e.name for e in root.children if e.name is not None]

    print(root_childs)

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

$ ./get_children.py 

['head', 'body']

Следовательно, у тегов html есть два дочерних элемента – head и body.

Атрибут descendants

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

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    root = soup.body

    

    root_childs = [e.name for e in root.descendants if e.name is not None]

    print(root_childs)

Этот пример дает возможность отыскать всех потомков главного тега body

$ ./get_descendants.py 

['h2', 'ul', 'li', 'li', 'li', 'li', 'li', 'p', 'p']

Перечисленные ранее теги – это потомки главного тега body.

BeautifulSoup и веб-скрапинг HTML

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

#!/usr/bin/python3




from bs4 import BeautifulSoup

import requests as req

    

resp = req.get("http://www.something.com")




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




print(soup.title)

print(soup.title.text)

print(soup.title.parent)

Этот пример показывает, как происходит извлечение имени веб-страницы. Здесь также выводится имя ее родителя. 

Python

resp = req.get("http://www.something.com")

 

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




Здесь мы получаем данные о самой странице.




Python

print(soup.title)

print(soup.title.text)

print(soup.title.parent)

Вышеприведенный код помогает вывести HTML-код заголовка, его текст, а также HTML-код его родителя. 

$ ./scraping.py 

<title>Something.</title>

Something.

<head><title>Something.</title></head>

Это результат вывода.

Метод prettify()

С помощью метода prettify() можно добиться того, чтобы код выглядел более красиво. 

#!/usr/bin/python3




from bs4 import BeautifulSoup

import requests as req

    

resp = req.get("http://www.something.com")




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




print(soup.prettify())

Так, мы выполняем оптимизацию HTML-кода простой веб-страницы. 

Shell

$ ./prettify.py 

<html>

 <head>

  <title>

   Something.

  </title>

 </head>

 <body>

  Something.

 </body>

</html>

После того, как мы запустили вышеприведенную программу, получили такой результат.

Метод find(), поиск элементов по айди

Метод find() дает возможность найти элементы страницы, пользуясь целым спектром опорных параметров, включая id

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    #print(soup.find("ul", attrs={ "id" : "mylist"}))

    print(soup.find("ul", id="mylist"))

В этом примере код находит тег ul, у которого id mylist. Строка в комментарии описывает альтернативный вариант, как выполняется аналогичное задание.

Поиск всех тегов

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

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    for tag in soup.find_all("li"):

        print("{0}: {1}".format(tag.name, tag.text))

В этом примере код ищет и выводит на экран все теги li. 

$ ./find_all.py 

li: Solaris

li: FreeBSD

li: Debian

li: NetBSD

А это результат вывода приложения, которое приведено только что.

Метод find_all() также используется в процессе поиска список из названий тегов. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    tags = soup.find_all(['h2', 'p'])

    

    for tag in tags:

        print(" ".join(tag.text.split()))

В этом примере видно, как осуществляется поиск элементов с тегами h2 и p, а потом их содержимое отображается на экране.

С помощью метода find_all() также можно определять, какие элементы должны быть выведены на экран. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

def myfun(tag):

    

    return tag.is_empty_element

 

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    tags = soup.find_all(myfun)

    print(tags)

Так, с помощью этого примера выводятся исключительно пустые элементы. 

$ ./find_by_fun.py 

[<meta charset="utf-8"/>]

В случае с вышеприведенным документом, единственный пустой элемент в документе – это meta.

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

#!/usr/bin/python3




import re




from bs4 import BeautifulSoup




with open("index.html", "r") as f:

    

    contents = f.read()




    soup = BeautifulSoup(contents, 'lxml')




    strings = soup.find_all(string=re.compile('BSD'))

    

    for txt in strings:

        

        print(" ".join(txt.split()))

#!/usr/bin/python3

 

import re

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    strings = soup.find_all(string=re.compile('BSD'))

    

    for txt in strings:

        

        print(" ".join(txt.split()))

В этом примере отображается содержимое элементов, в каких есть строка с символами ‘BSD’

$ ./regex.py 

FreeBSD

NetBSD

FreeBSD is an advanced computer operating system used to power modern servers, desktops, and embedded platforms.

Это результат вывода.

Использование методов select() и select_one()

С использованием методов select() и select_one() возможно задействование ряда CSS-селекторов

#!/usr/bin/python3




from bs4 import BeautifulSoup




with open("index.html", "r") as f:

    

    contents = f.read()




    soup = BeautifulSoup(contents, 'lxml')




    print(soup.select("li:nth-of-type(3)"))

В этом примере используется CSS-селектор, выводящий на экран HTML-код элемента списка, который будет расположен третьим по счету. 

$ ./select_nth_tag.py 

<li>Debian</li>

Именно этот элемент является третьим в списке.

В CSS символ решетки отвечает за выбор тегов по id

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    print(soup.select_one("#mylist"))

Этот пример позволяет отображать элементы, у которых есть id с названием mylist.

BeautifulSoup – использование метода append()

С помощью этого метода программа добавляет в HTML-документ новый тег. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    newtag = soup.new_tag('li')

    newtag.string='OpenBSD'

 

    ultag = soup.ul

    

    ultag.append(newtag)

    

    print(ultag.prettify())

В приведенном выше примере отображается, как добавить новый элемент li

newtag = soup.new_tag('li')

newtag.string='OpenBSD'

Сперва, надо создать новый тег, используя метод new_tag()

ultag = soup.ul.

Затем необходимо сделать сноску на тег ul

ultag.append(newtag)

Потом тег li, который создан на предыдущем этапе, добавляется к тегу ul

print(ultag.prettify())

В результате, у нас получилось добиться идеального форматирования тега ul.

Метод insert() – вставка HTML-тега

С помощью метода insert() можно выбирать определенное место и вставлять туда определенный элемент. Работает это следующим образом. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    newtag = soup.new_tag('li')

    newtag.string='OpenBSD'

 

    ultag = soup.ul

    

    ultag.insert(2, newtag)

    

    print(ultag.prettify())

В примере видно, как поставить тег li на третью позицию в выбранном ul теге.

Использование метода replace_with() для замены текста в теге

Если необходимо заменить содержимое определенного элемента, используется метод replace_with().  

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    tag = soup.find(text="Windows")

    tag.replace_with("OpenBSD")

    

    print(soup.ul.prettify())

В этом примере видно, как с помощью метода find() можно найти определенный элемент, а затем, с помощью метода replace_with() заменить его содержимое.

Использование метода decompose() для удаления HTML-тега

А вот с помощью метода decompose() можно убрать определенный тег из документа. Работает это следующим образом. 

#!/usr/bin/python3

 

from bs4 import BeautifulSoup

 

with open("index.html", "r") as f:

    

    contents = f.read()

 

    soup = BeautifulSoup(contents, 'lxml')

 

    ptag2 = soup.select_one("p:nth-of-type(2)")

     

    ptag2.decompose()

    

    print(soup.body.prettify())

Здесь видно, как удалить второй элемент p в документе.

ОфисГуру
Adblock
detector