Работа с веб-страницами не ограничивается одним лишь их созданием или открытием. Например, может понадобиться открыть на них какую-то информацию. Сегодня поговорим о том, как использовать библиотеку BeautifulSoup Python. В частности, разберемся, как с ее помощью использовать те или иные теги, модифицировать документы, осуществлять перебор его элементов, а также как выполнять парсинг веб-страниц.
- Примеры BeautifulSoup
- Как установить BeautifulSoup в Python
- Пример кода HTML-страницы
- Простой пример парсинга HTML с использованием BeautifulSoup
- Теги, атрибуты nameи text
- BeautifulSoup – перебор тегов HTML
- BeautifulSoup – использование атрибута children
- Атрибут descendants
- BeautifulSoup и веб-скрапинг HTML
- Метод prettify()
- Метод find(), поиск элементов по айди
- Поиск всех тегов
- Использование методов select()и select_one()
- BeautifulSoup – использование метода append()
- Метод insert() – вставка HTML-тега
- Использование метода replace_with()для замены текста в теге
- Использование метода decompose()для удаления HTML-тега
Примеры 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 в документе.