J'ai ci-dessous des blocs HTML, qui sont générés par pdftotext
en utilisant l'option -bbox-layout
:
areas[0] is between 100 and 200 areas[1] is between 200 and 612
Maintenant, je J'essaie d'analyser dynamiquement la structure ci-dessus et d'obtenir chaque contenu de
, où les valeurs xMin
et xMax est entre deux nombres.
Imaginez que j'ai des nombres ci-dessous:
areas[0] = (100, 0, 200, 792) areas[1] = (200, 0, 612, 792) with open(path_to_html_document) as html_file: parsed_html = BeautifulSoup(html_file) for (i, area) in enumerate(areas): xMinValue, xMaxValue = areas[i][0], areas[i][2] block_tags = parsed_html.find_all( "block", attrs={"xMin": xMinValue, "xMax": xMaxValue}) print(block_tags)
Le code ci-dessus ne renvoie rien, car il n'y a pas de balises correspondantes . find_all ()
recherche des correspondances exactes pour les balises block
avec les numéros spécifiques - mais j'essaie de rechercher les balises block
, où xMin et xMax est:
<flow> <block xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="116.233001"> <line xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000"> <word xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000"> My text string located here!</word> </line> </block> </flow> [...] <flow> <block xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500"> <line xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500"> <word xMin="223.560000" yMin="323.675000" xMax="316.836500" yMax="339.855500">Another string </word> <word xMin="320.022000" yMin="323.675000" xMax="345.563500" yMax="339.855500">And another!</word> </line> </block> </flow>
Est-ce possible avec BeautifulSoup?
3 Réponses :
Essayez
target = filter(lambda x: x["xMin"] == "1" and x["xMax"] == 2, all_blocks)
et filtrez le résultat avec les clés "xMin" et "xMax".
Par exemple, si vous voulez obtenir
, vous pouvez d'abord obtenir toutes les balises block
par
all_blocks = parsed_html.select("block")
Et vous voulez obtenir l'un des bloc
dont xMin
est 1 et xMax
est 2, vous pouvez le faire comme:
parsed_html.select("block")
Pourriez-vous fournir un peu plus d'informations? Comment cela peut-il résoudre mon problème actuel, où j'ai besoin d'obtenir des balises où xMin
et xMax
se trouvent entre un ensemble de nombres?
Vous pouvez sélectionner Impressions:
avec les attributs xMin
et xMax
avec le sélecteur CSS block [xMin] [xMax] code>. Ensuite, vous filtrez à travers la compréhension de liste:
<block xmax="178.647000" xmin="21.600000" ymax="116.233001" ymin="86.356000">
<line xmax="178.647000" xmin="21.600000" ymax="101.833000" ymin="86.356000">
<word xmax="178.647000" xmin="21.600000" ymax="101.833000" ymin="86.356000">
My text string located here!
</word>
</line>
</block>
data = '''<flow>
<block xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="116.233001">
<line xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000">
<word xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000">
My text string located here!</word>
</line>
</block>
</flow>
<flow>
<block xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500">
<line xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500">
<word xMin="223.560000" yMin="323.675000" xMax="316.836500" yMax="339.855500">Another string
</word>
<word xMin="320.022000" yMin="323.675000" xMax="345.563500" yMax="339.855500">And another!</word>
</line>
</block>
</flow>'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(data, 'lxml')
def blocks_min_max(soup, x_min, x_max):
return [b for b in soup.select('block[xMin][xMax]') if float(b['xmin']) >= x_min and float(b['xmax']) <= x_max]
for b in blocks_min_max(soup, 10, 200):
print(b.prettify())
Merci Andrej! Cependant, cela me donne l'erreur suivante: Sélecteur CSS non pris en charge ou non valide: "block [xMin] [xMax]
@oliverbj Quelle version de BeautifulSoup utilisez-vous? Je suis sur beautifulsoup4 == 4.7.1
Remplacez votre code:
block_tags = parsed_html.find_all("block") for block in block_tags: if float(block['xmin']) >= xMinValue and float(block['xmax']) <= xMinValue: print(block)
TO:
block_tags = parsed_html.find_all( "block", attrs={"xMin": xMinValue, "xMax": xMaxValue}) print(block_tags)
Si le code html de débogage print (parsed_html)
, vous verrez bloc html
tous les attributs en minuscule.
Dans l'instruction if float (...
, est-il censé être 2x valeurs xmin
que nous vérifions? Pas xMax
?