Как проверить, какая строка из HTML вызывает ошибку? - PullRequest
1 голос
/ 04 марта 2020

У меня есть следующий код, который удаляет дубликаты абзацев из файла html.

from bs4 import BeautifulSoup

fp = open("Input.html", "rb")
soup = BeautifulSoup(fp, "html5lib")

elms = []
for elem in soup.find_all('font'):
    if elem not in elms:
        elms.append(elem)
    else:
        target =elem.findParent().findParent()
        target.decompose()
print(soup.html)

Почти работает, но для некоторых элементов я получаю эту ошибку

attributeerror: 'nonetype' object has no attribute 'findparent'

Есть ли способ напечатать номер строки в файле HTML, где происходит ошибка, чтобы проверить, в каком формате?

структура элементов, для которых у кода нет проблем, выглядит следующим образом

<!DOCTYPE html>
<html>
  <body>
      <p align="left">
        <b><font face="Times New Roman" size="5" color="red">Some text</font></b> 
      </p>
  </body>
</html>

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

1 Ответ

1 голос
/ 04 марта 2020

Поскольку вы используете парсер html5lib , у вас есть доступ к белью, если вы используете BeautifulSoup версии 4.8.1 или выше, как описано в документах :

Синтаксические анализаторы html.parser и html5lib могут отслеживать, где в исходном документе был найден каждый тег. Вы можете получить доступ к этой информации как Tag.sourceline (номер строки) и Tag.sourcepos (позиция начального тега в строке) […]

В вашем примере вы можете легко получить доступ к этой информации:

from bs4 import BeautifulSoup

html = """<!DOCTYPE html>
<html>
  <body>
      <p align="left">
        <b><font face="Times New Roman" size="5" color="red">Some text</font></b> 
      </p>
  </body>
</html>
"""

soup = BeautifulSoup(html, "html5lib")

for elem in soup.find_all('font'):
    print(elem.sourceline, elem.sourcepos, elem.string)

Это выведет 5 60 Some text, где первый номер - ваш номер белья.

Если есть какая-либо потенциальная ошибка, например, получение NoneType, вы должны позаботиться об этом до достижения ошибки. Поэтому вместо этого:

target = elem.findParent().findParent()

вы можете сначала проверить, получаете ли вы результат для вашего первого findParent() -метода, а затем выполнить второй запрос, например:

target = elem.findParent()
err_line, err_source, err_str = target.sourceline, target.sourcepos, target.string
if target:
    target = target.findParent()
else:
    print(f"Error near line {err_line} ({err_source}). Last good text: {err_str}")
...