Работа с BeautifulSoup4

Замечание
Последний раз данная статья обновлялась 17.01.2023, информация может быть устаревшей.
1
pip install beautifulsoup4 requests urllib3

Beautiful Soup поддерживает HTML-парсер, включенный в стандартную библиотеку Python, но также поддерживает ряд сторонних парсеров:

  • html.parser - стандартный питоновский парсер. Нестрогий, имеет приемлемую скорость, но не такой быстрый, как lxml и более строгий, чем html5lib.
  • HTML-парсер в lxml - очень быстрый, нестрогий, но имеющий внешнюю зависимость от C
  • XML-парсер в lxml - eдинственный поддерживаемый XML-парсер. Очень быстрый, но имеет внешнюю зависимость от C
  • html5lib - разбирает страницы так же, как это делает браузер. Создает валидный HTML5. Очень нестрогий, очень медленный и имеет внешнюю зависимость от Python
1
pip install lxml

Чтобы распарсить документ, нужно передать в конструктор BeautifulSoup строку. Этой строкой и будет полученный html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from bs4 import BeautifulSoup
import requests
from loguru import logger


url = 'https://www.aoosk.ru/press-center/news/'
try:
    page = requests.get(url)
except requests.exceptions.RequestException as e:
    logger.error('Error: {}', e)

soup = BeautifulSoup(page.text, 'html.parser')

page.text - возвращает HTML-содержимое объекта ответа в Unicode. page.content - возвращает содержимое ответа в байтах. page.headers.get("content-type", "unknown") - можно проверить какой тип контента вернулся.

Beautiful Soup превращает сложный HTML-документ в сложное дерево объектов Python. Однако нам придется иметь дело только с четырьмя видами объектов: Tag, NavigableString, BeautifulSoup и Comment.

  • InsecureRequestWarning: Unverified HTTPS request is being made to host xxx Подробное решение тут
1
2
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
  • TypeError: object of type ‘Response’ has no len()

Скорее всего в качестве первого параметра в BS4 передана не строка, а что-то другое. Убедитесь, что передаете не response, а response.text.

  • Error: HTTPSConnectionPool(host=‘some_host’, port=443): Max retries exceeded with url: /some/path/ (Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)’)))

В этом случае нужно либо отключить проверку SSL-сертификата (плохое решение)

1
page = requests.get(url, verify=False)

Либо (что гораздо лучше) создать сессиию и примонтировать адаптер:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import requests
from requests.adapters import HTTPAdapter, Retry


def session() -> requests.Session:
    session = requests.Session()
    retries = Retry(
        total=2,
        read=2,
        connect=2,
        backoff_factor=0.3,
        status_forcelist=[
            500,
            502,
            503,
            504,
        ]
    )
    adapter = HTTPAdapter(max_retries=retries)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    session.verify = False
    return session
def parse():
    url = 'https://ya.ru'
    ses = session()
    try:
        page = ses.get(url)
    except requests.exceptions.RequestException as e:
        logger.error('Error: {}', e)

Если у вас Mac и python установлен через brew, то ошибка может возникать из-за того, что по какой-то причине brew не запустил команду Install_Certificates.command, которая поставляется в пакете Python3 для Mac. Решение тут

Последний вариант: чтобы использовать непроверенный ssl, вы можете добавить это в свой код:

1
2
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

Источники 12