Come stimolare l’HTML in modo che gli attributi dei tag rimangano in un’unica riga?

Ho questo piccolo pezzo di codice:

text = """ 

Main site

Testing static images

""" import sys import re import bs4 def prettify(soup, indent_width=4): r = re.compile(r'^(\s*)', re.MULTILINE) return r.sub(r'\1' * indent_width, soup.prettify()) soup = bs4.BeautifulSoup(text, "html.parser") print(prettify(soup))

L’output dello snippet qui sopra è ora:

     

Main site

text1

text2

Testing static images

Mi piacerebbe capire come formattare l’output in modo che diventi questo invece:

     

Main site

text1

text2

Testing static images

Detto altrimenti, mi piacerebbe mantenere istruzioni html come in una sola riga, se ansible. Quando dico “se ansible” intendo senza rovinare il valore degli attributi stessi (valore1, valore2, …, valore).

È ansible raggiungere questo objective con beautifulsoup4? Finora ho letto nei documenti sembra che tu possa usare un formattatore personalizzato ma non so come potrei avere un formattatore personalizzato in modo che possa soddisfare i requisiti descritti.

MODIFICARE:

La soluzione @alecxe è abbastanza semplice, sfortunatamente fallisce in alcuni casi più complessi come il seguente, ovvero:

 test1 = """ 
""" from bs4 import BeautifulSoup import re def prettify(soup, indent_width=4, single_lines=True): if single_lines: for tag in soup(): for attr in tag.attrs: print(tag.attrs[attr], tag.attrs[attr].__class__) tag.attrs[attr] = " ".join( tag.attrs[attr].replace("\n", " ").split()) r = re.compile(r'^(\s*)', re.MULTILINE) return r.sub(r'\1' * indent_width, soup.prettify()) def html_beautify(text): soup = BeautifulSoup(text, "html.parser") return prettify(soup) print(html_beautify(test1))

RINTRACCIARE:

 dialer-capmaign-console  ['fill-vertically']  Traceback (most recent call last): File "d:\mcve\x.py", line 35, in  print(html_beautify(test1)) File "d:\mcve\x.py", line 33, in html_beautify return prettify(soup) File "d:\mcve\x.py", line 25, in prettify tag.attrs[attr].replace("\n", " ").split()) AttributeError: 'list' object has no attribute 'replace' 

BeautifulSoup cercato di preservare le newline e gli spazi multipli presenti nei valori degli attributi nell’input HTML.

Una soluzione alternativa sarebbe quella di iterare sugli attributi dell’elemento e pulirli prima di procedere alla stimolazione – rimuovendo le newline e sostituendo più spazi consecutivi con un singolo spazio:

 for tag in soup(): for attr in tag.attrs: tag.attrs[attr] = " ".join(tag.attrs[attr].replace("\n", " ").split()) print(soup.prettify()) 

stampe:

     

Main site

text1

text2

Testing static images


Aggiornamento (per indirizzare gli attributi multivalore come class ):

Devi solo aggiungere una leggera modifica aggiungendo una gestione speciale per il caso quando un attributo è di un tipo di list :

 for tag in soup(): tag.attrs = { attr: [" ".join(attr_value.replace("\n", " ").split()) for attr_value in value] if isinstance(value, list) else " ".join(value.replace("\n", " ").split()) for attr, value in tag.attrs.items() } 

Mentre BeautifulSoup è più comunemente usato, HTML Tidy può essere una scelta migliore se stai lavorando con stranezze e hai requisiti più specifici.

Dopo aver installato la libreria per Python ( pip install pytidylib ) prova il seguente codice:

 from tidylib import Tidy tidy = Tidy() # assign string to text config = { "doctype": "omit", # "show-body-only": True } print tidy.tidy_document(text, options=config)[0] 

tidy.tidy_document restituisce una tupla con l’HTML e gli eventuali errori che potrebbero essersi verificati. Questo codice verrà emesso

      

Main site

text1

text2

Testing static images

Rimuovendo il commento dallo "show-body-only": True per il secondo campione.

 

Vedi più configurazione per ulteriori opzioni e personalizzazioni. Ci sono opzioni di wrapping specifiche per gli attributi che possono aiutare. Come puoi vedere, gli elementi vuoti occuperanno solo una riga, e html-tidy cercherà automaticamente di aggiungere cose come DOCTYPE , title head e title .