2008-08-30 54 views
29

如何验证文档是否遵循某个HTML版本(我可以指定优先)?我希望能够知道失败发生的位置,例如在基于Web的验证器中,除了原生Python应用程序。在Python中验证(X)HTML

+0

请注意,验证与整理不同!人们发布的一些答案是关于自动更正HTML,而不是仅仅验证HTML是否有效。 – Flimm 2017-05-26 12:00:49

回答

8

XHTML很简单,使用lxml

HTML比较困难,因为传统上对HTML验证(通过验证器,yikes运行StackOverflow本身)没有那么多兴趣。最简单的解决方案是执行外部应用程序,例如nsgmlsOpenJade,然后解析其输出。

+0

注意:lxml链接已损坏。也许使用[this one](http://lxml.de/)? – 2014-07-10 18:17:57

3

我认为HTML tidy会做你想做的。它有一个Python绑定。

5

尝试tidylib。你可以得到一些真正基本的绑定作为元素模块的一部分(从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 

解析日志应该给你几乎所有你需要的东西。

11

您可以决定在本地安装HTML验证程序并创建一个客户端来请求验证。

这里我做了一个程序来验证一个txt文件中的URL列表。我只是检查头部以获得验证状态,但如果您执行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 
+2

不幸的是,`html5lib` [不验证](http://stackoverflow.com/a/29992363/593047)。 – 2017-01-25 01:15:39

22

PyTidyLib是一个不错的Python Tidy的Python绑定。他们的例子:

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 

而且它与两个legacy HTML Tidynew tidy-html5兼容。

+3

Debian中的软件包:python-tidylib – sumid 2012-10-22 22:26:15

15

我觉得最优雅的方式,来调用W3C验证服务在

http://validator.w3.org/ 

编程。很少有人知道,你不必为了得到结果屏幕刮的结果,因为服务返回非标准的HTTP标头PARAMATERS

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) 
+6

W3C Validator还有一个完整的Web服务API和一个Python绑定到它:https://bitbucket.org/nmb10/py_w3c – 2012-05-09 16:22:30

0

在我的情况下,python W3C/HTML验证包不起作用pip search w3c(截至2016年9月)。

我解决了这个在这里python requests

$ 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. 

>>> r = requests.post('https://validator.w3.org/nu/', 
...     data=file('index.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":[{"type":"info", ... 

>>> r.json() 
>>> {u'messages': [{u'lastColumn': 59, ... 

更多的文档,W3C Validator API

0

这是一个基于LXML的HTMLParser的一个非常基本的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</a>") 

但不会如下:

validate_html("<a href='example.com'>foo</a")