2008-08-30 12 views
29

Jaki jest najlepszy sposób sprawdzenia, czy dokument podąża za jakąś wersją HTML (najlepiej, gdy mogę to określić)? Chciałbym wiedzieć, gdzie występują awarie, tak jak w przeglądarce sieciowej, z wyjątkiem natywnej aplikacji Python.Sprawdzanie poprawności (X) HTML w Pythonie

+0

Należy pamiętać, że walidacji różni się od sprzątania! Niektóre z odpowiedzi publikowanych przez użytkowników dotyczą automatycznego korygowania kodu HTML, a nie tylko sprawdzania poprawności kodu HTML. – Flimm

Odpowiedz

8

XHTML jest łatwy, użyj lxml.

HTML jest trudniejszy, ponieważ tradycyjnie nie ma tak dużego zainteresowania sprawdzaniem poprawności wśród tłumu HTML (uruchamianie samego StackOverflow za pomocą walidatora, yikes). Najprostszym rozwiązaniem byłoby wykonanie zewnętrznych aplikacji, takich jak nsgmls lub OpenJade, a następnie przeanalizowanie ich wyników.

+0

Uwaga: link LXML jest uszkodzony. Może skorzystasz z [tego] (http://lxml.de/)? –

3

Myślę, że HTML tidy zrobi to, co chcesz. Istnieje powiązanie z Pythonem.

5

Wypróbuj tidylib. Możesz uzyskać naprawdę proste powiązania w ramach modułu elementtidy (buduje elementy z dokumentów 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 

Parsowanie dziennika powinno dać ci wszystko, czego potrzebujesz.

11

Możesz zdecydować się lokalnie zainstalować weryfikator HTML i utworzyć klienta, aby poprosić o sprawdzenie poprawności.

Tutaj zrobiłem program do sprawdzania poprawności listy adresów URL w pliku txt. Właśnie sprawdzałem HEAD, aby uzyskać status sprawdzania poprawności, ale jeśli wykonasz GET, uzyskasz pełne wyniki. Spójrz na API walidatora, istnieje wiele opcji dla niego.

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

Niestety, 'html5lib' [nie sprawdza poprawności] (http://stackoverflow.com/a/29992363/593047). –

22

PyTidyLib to ładne wiązanie python dla HTML Tidy. Ich przykład:

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 

Ponadto jest kompatybilny zarówno z legacy HTML Tidy i new tidy-html5.

+3

Pakiet w systemie Debian: python-tidylib – sumid

15

Myślę, że to najbardziej elegancki sposób, aby wywołać walidator W3C na

http://validator.w3.org/ 

programowo. Niewiele osób wie, że nie masz do ekranu zeskrobać wyników w celu uzyskania wyników, ponieważ usługa zwraca niestandardowy nagłówek HTTP paramaters

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

wskazujące na ważność i liczbę błędów i ostrzeżeń.

Na przykład, linia poleceń

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

powraca

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 

sposób można elegancko wywołać walidator W3C i wyodrębnić wynika z nagłówka 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

Istnieje również pełny interfejs API usług WWW do W3C Validator i powiązanie z nim w Pythonie: https://bitbucket.org/nmb10/py_w3c –

+0

Ten adres URL zwraca obecnie 302, a nie 200. Nie działa teraz! – sreeraag

0

W moim przypadku pakiety sprawdzania poprawności Pythona W3C/HTML nie działały pip search w3c (według stanu na wrzesień 2016).

I rozwiązać ten z

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

Więcej dokumentacji tutaj python requests, W3C Validator API

0

Jest to bardzo podstawowy walidator HTML na podstawie lxml za HTMLParser. Nie wymaga żadnego połączenia z Internetem.

_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) 

Należy pamiętać, że to nie będzie sprawdzał zamykających znaczników, tak na przykład, następujące minie:

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

Jednak po przyzwyczajenie:

validate_html("<a href='example.com'>foo</a") 
Powiązane problemy