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






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не подтверждает.
PyTidyLib - хорошая привязка Python для HTML Tidy. Их пример:
from tidylib import tidy_document
document, errors = tidy_document('''<p>fõo <img src = "bar.jpg">''',
options = {'numeric-entities':1})
print document
print errors
Более того, он совместим как с устаревшая HTML Tidy, так и с новый tidy-html5.
Пакет в Debian: python-tidylib
Я думаю, что самый элегантный способ вызвать службу валидации 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. Сейчас не работает!
В моем случае пакеты проверки 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. Но у меня это единственный работает без установки ничего другого. Спасибо.
Модуль 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.
Обратите внимание, что проверка отличается от наведения порядка! Некоторые из ответов, которые публикуют люди, касаются автоматического исправления HTML, а не простой проверки правильности HTML.