Проверить (X) HTML в Python

Как лучше всего проверить, соответствует ли документ какой-либо версии HTML (желательно, чтобы я мог указать)? Я хотел бы знать, где происходят сбои, как в веб-валидаторе, за исключением собственного приложения Python.

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

Flimm 26.05.2017 15:00
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
37
1
20 647
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Ответ принят как подходящий

XHTML прост, используйте lxml.

from lxml import etree
from StringIO import StringIO
etree.parse(StringIO(html), etree.HTMLParser(recover=False))

HTML сложнее, поскольку толпа HTML традиционно не проявляет особого интереса к валидации (запустите сам StackOverflow через валидатор, yikes). Самым простым решением было бы запустить внешние приложения, такие как nsgmls или OpenJade, а затем проанализировать их вывод.

Думаю, что HTML аккуратный будет делать то, что вы хотите. Для этого есть привязка Python.

Попробуйте тидилиб. Вы можете получить действительно базовые привязки как часть модуля elementtidy (строит деревья элементов из документов HTML). http://effbot.org/downloads/#elementtidy

>>> import _elementtidy
>>> xhtml, log = _elementtidy.fixup("<html></html>")
>>> print log
line 1 column 1 - Warning: missing <!DOCTYPE> declaration
line 1 column 7 - Warning: discarding unexpected </html>
line 1 column 14 - Warning: inserting missing 'title' element

Анализ журнала должен дать вам почти все, что вам нужно.

Вы можете решить установить HTML-валидатор локально и создать клиента для запроса валидации.

Здесь я создал программу для проверки списка URL-адресов в текстовом файле. Я просто проверял HEAD, чтобы получить статус проверки, но если вы выполните GET, вы получите полные результаты. Посмотрите API валидатора, там вариантов масса.

import httplib2
import time

h = httplib2.Http(".cache")

f = open("urllistfile.txt", "r")
urllist = f.readlines()
f.close()

for url in urllist:
   # wait 10 seconds before the next request - be nice with the validator
   time.sleep(10)
   resp= {}
   url = url.strip()
   urlrequest = "http://qa-dev.w3.org/wmvs/HEAD/check?doctype=HTML5&uri = "+url
   try:
      resp, content = h.request(urlrequest, "HEAD")
      if resp['x-w3c-validator-status'] == "Abort":
         print url, "FAIL"
      else:
         print url, resp['x-w3c-validator-status'], resp['x-w3c-validator-errors'], resp['x-w3c-validator-warnings']
   except:
      pass

К сожалению, html5libне подтверждает.

ron rothman 25.01.2017 04:15

PyTidyLib - хорошая привязка Python для HTML Tidy. Их пример:

from tidylib import tidy_document
document, errors = tidy_document('''<p>f&otilde;o <img src = "bar.jpg">''',
    options = {'numeric-entities':1})
print document
print errors

Более того, он совместим как с устаревшая HTML Tidy, так и с новый tidy-html5.

Пакет в Debian: python-tidylib

sumid 23.10.2012 02:26

Я думаю, что самый элегантный способ вызвать службу валидации W3C по адресу

http://validator.w3.org/

программно. Мало кто знает, что вам не нужно очищать экран от результатов, чтобы получить результаты, потому что служба возвращает нестандартные параметры заголовка HTTP.

X-W3C-Validator-Recursion: 1
X-W3C-Validator-Status: Invalid (or Valid)
X-W3C-Validator-Errors: 6
X-W3C-Validator-Warnings: 0

для указания действительности и количества ошибок и предупреждений.

Например, командная строка

curl -I "http://validator.w3.org/check?uri=http%3A%2F%2Fwww.stalsoft.com"

возвращается

HTTP/1.1 200 OK
Date: Wed, 09 May 2012 15:23:58 GMT
Server: Apache/2.2.9 (Debian) mod_python/3.3.1 Python/2.5.2
Content-Language: en
X-W3C-Validator-Recursion: 1
X-W3C-Validator-Status: Invalid
X-W3C-Validator-Errors: 6
X-W3C-Validator-Warnings: 0
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
Connection: close

Таким образом, вы можете элегантно вызвать службу проверки W3C и извлечь результаты из заголовка HTTP:

# Programmatic XHTML Validations in Python
# Martin Hepp and Alex Stolz
# [email protected] / [email protected]

import urllib
import urllib2

URL = "http://validator.w3.org/check?uri=%s"
SITE_URL = "http://www.heppnetz.de"

# pattern for HEAD request taken from 
# http://stackoverflow.com/questions/4421170/python-head-request-with-urllib2

request = urllib2.Request(URL % urllib.quote(SITE_URL))
request.get_method = lambda : 'HEAD'
response = urllib2.urlopen(request)

valid = response.info().getheader('X-W3C-Validator-Status')
if valid == "Valid":
    valid = True
else:
    valid = False
errors = int(response.info().getheader('X-W3C-Validator-Errors'))
warnings = int(response.info().getheader('X-W3C-Validator-Warnings'))

print "Valid markup: %s (Errors: %i, Warnings: %i) " % (valid, errors, warnings)

Этот URL-адрес сейчас возвращает 302, а не 200. Сейчас не работает!

sreeraag 29.12.2015 14:14

В моем случае пакеты проверки python W3C / HTML cli не работали (по состоянию на сентябрь 2016 г.).

Я сделал это вручную с помощью requests вот так

код:

r = requests.post('https://validator.w3.org/nu/', 
    data=open('FILE.html','rb').read(), params = {'out': 'json'}, 
    headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101    Safari/537.36', 
    'Content-Type': 'text/html; charset=UTF-8'})

print r.json()

в консоли:

$ echo '<!doctype html><html lang=en><head><title>blah</title></head><body></body></html>' | tee FILE.html 
$ pip install requests

$ python
Python 2.7.12 (default, Jun 29 2016, 12:46:54)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

>>> import requests

>>> r = requests.post('https://validator.w3.org/nu/', 
...                    data=open('FILE.html', 'rb').read(), 
...                    params = {'out': 'json'}, 
...                    headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36', 
...                    'Content-Type': 'text/html; charset=UTF-8'})

>>> r.text
>>> u'{"messages":[]}\n'

>>> r.json()
>>> {u'messages': []}

Дополнительная документация здесь запросы python, API валидатора W3C

Это очень простой валидатор HTML, основанный на HTMLParser lxml. Это не полный валидатор html, но он выполняет несколько базовых проверок, не требует подключения к Интернету и большой библиотеки.

_html_parser = None
def validate_html(html):
    global _html_parser
    from lxml import etree
    from StringIO import StringIO
    if not _html_parser:
        _html_parser = etree.HTMLParser(recover = False)
    return etree.parse(StringIO(html), _html_parser)

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

validate_html("<a href='example.com'>foo")
> <lxml.etree._ElementTree at 0xb2fd888>

Тем не менее, следующее:

validate_html("<a href='example.com'>foo</a")
> XMLSyntaxError: End tag : expected '>', line 1, column 29

Когда я нашел этот ответ, оценка была -1. Но у меня это единственный работает без установки ничего другого. Спасибо.

HuongOrchid 09.05.2019 16:39

Модуль html5lib можно использовать для проверки документа HTML5:

>>> import html5lib
>>> html5parser = html5lib.HTMLParser(strict=True)
>>> html5parser.parse('<html></html>')
Traceback (most recent call last):
  ...
html5lib.html5parser.ParseError: Unexpected start tag (html). Expected DOCTYPE.

Другие вопросы по теме