Valider (X)HTML en Python
-
09-06-2019 - |
Question
Quelle est la meilleure façon de valider qu'un document suit une version de HTML (de préférence que je puisse spécifier) ?J'aimerais pouvoir savoir où se produisent les échecs, comme dans un validateur Web, sauf dans une application Python native.
La solution
XHTML est simple, utilisez lxml.
Le HTML est plus difficile, car il n'y a traditionnellement pas autant d'intérêt pour la validation parmi la foule HTML (exécutez StackOverflow lui-même via un validateur, ouais).La solution la plus simple serait d'exécuter des applications externes telles que nsgmls ou OuvertJade, puis analysez leur sortie.
Autres conseils
PyTidyLib est une belle liaison python pour HTML Tidy.Leur exemple :
from tidylib import tidy_document
document, errors = tidy_document('''<p>fõo <img src="bar.jpg">''',
options={'numeric-entities':1})
print document
print errors
De plus, il est compatible avec les deux héritage HTML Tidy et le nouveau bien rangé-html5.
Je pense que la manière la plus élégante d'invoquer le service de validation du W3C à
http://validator.w3.org/
par programmation.Peu de gens savent que vous n'avez pas besoin de gratter l'écran pour obtenir les résultats, car le service renvoie des paramètres d'en-tête HTTP non standard.
X-W3C-Validator-Recursion: 1
X-W3C-Validator-Status: Invalid (or Valid)
X-W3C-Validator-Errors: 6
X-W3C-Validator-Warnings: 0
pour indiquer la validité et le nombre d'erreurs et d'avertissements.
Par exemple, la ligne de commande
curl -I "http://validator.w3.org/check?uri=http%3A%2F%2Fwww.stalsoft.com"
Retour
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
Ainsi, vous pouvez invoquer avec élégance le service de validation du W3C et extraire les résultats de l'en-tête HTTP :
# Programmatic XHTML Validations in Python
# Martin Hepp and Alex Stolz
# mhepp@computer.org / alex.stolz@ebusiness-unibw.org
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)
Vous pouvez décider d'installer le validateur HTML localement et créer un client pour demander la validation.
Ici, j'avais créé un programme pour valider une liste d'urls dans un fichier txt.Je vérifiais juste le HEAD pour obtenir le statut de validation, mais si vous effectuez un GET, vous obtiendrez les résultats complets.Regardez l'API du validateur, il existe de nombreuses options pour cela.
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
Essayez Tidylib.Vous pouvez obtenir des liaisons vraiment basiques dans le cadre du module elementtidy (construit des arbres d'éléments à partir de documents 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
L'analyse du journal devrait vous donner à peu près tout ce dont vous avez besoin.
je pense que HTML bien rangé tu feras ce que tu veux.Il existe une liaison Python pour cela.
Dans mon cas, les packages de validation python W3C/HTML n'ont pas fonctionné pip search w3c
(en septembre 2016).
J'ai résolu ça avec
$ 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, ...
Plus de documentation ici requêtes python, API du validateur W3C
Il s'agit d'un validateur HTML très basique basé sur HTMLParser de lxml.Il ne nécessite aucune connexion Internet.
_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)
Notez que cela ne vérifiera pas les balises de fermeture, donc par exemple, ce qui suit sera réussi :
validate_html("<a href='example.com'>foo</a>")
Cependant, les éléments suivants :
validate_html("<a href='example.com'>foo</a")