Ich arbeite an einem Projekt, um spezifische Informationen aus lokal gespeicherten HTML-Dateien mit BS4 zu extrahieren. Da ich sehr viele Dateien habe (> 1 Million), ist Geschwindigkeit und Leistung der Schlüssel für einen nützlichen Code, der alle Dateien durchsucht. Bis jetzt arbeite ich mit BS4, da ich vorher an einem Web-Crawler gearbeitet habe und ich dachte BS4 ist ziemlich einfach und praktisch. Wenn es jedoch um Big Data geht, ist BS4 viel zu langsam. Ich lese über die lxml parser
und html.parser
, die die einfachsten und schnellsten Parser unter Python für HTML-Dokumente zu sein scheint.Codetransformation von BS4 nach lxml-Parser
So jetzt mein Code wie folgt aussieht:
from bs4 import BeautifulSoup
import glob
import os
import re
import contextlib
@contextlib.contextmanager
def stdout2file(fname):
import sys
f = open(fname, 'w')
sys.stdout = f
yield
sys.stdout = sys.__stdout__
f.close()
def trade_spider():
os.chdir(r"C:\Users\XXX")
with stdout2file("output.txt"):
for file in glob.iglob('**/*.html', recursive=True):
with open(file, encoding="utf8") as f:
contents = f.read()
soup = BeautifulSoup(contents, "html.parser")
for item in soup.findAll("ix:nonfraction"):
if re.match(".*SearchTag", item['name']):
print(file.split(os.path.sep)[-1], end="| ")
print(item['name'], end="| ")
print(item.get_text())
break
trade_spider()
Es eine Textdatei öffnet, geht in mein Set-Verzeichnis (os.chdir (..)), alle Dateien seraches durch .html endet, liest die Inhalt und wenn es ein Tag mit dem Namensattribut "SearchTag" findet, nimmt es den zugehörigen HTML-Text und druckt es in meine geöffnete Textdatei. Nach einem Match gibt es eine Pause und es wird mit der nächsten fortgesetzt. Also was ich gelesen habe ist, dass BS4 dies alles im Speicher macht, was die Verarbeitungszeit signifikant erhöht.
Deshalb wollte ich meinen Code ändern, entweder mit lxml (bevorzugt) oder html.parser.
Jeder von euch ist ein Genie und ist in der Lage, meinen Code zu ändern, um lxml Parser zu verwenden, ohne die anfängliche einfache Idee, die ich dabei hatte, zu ändern?
Jede auf diese geschätzte Hilfe, da ich total stucked bin ....
UPDATE:
import lxml.etree as et
import os
import glob
import contextlib
@contextlib.contextmanager
def stdout2file(fname):
import sys
f = open(fname, 'w')
sys.stdout = f
yield
sys.stdout = sys.__stdout__
f.close()
def skip_to(fle, line):
with open(fle) as f:
pos = 0
cur_line = f.readline().strip()
while not cur_line.startswith(line):
pos = f.tell()
cur_line = f.readline()
f.seek(pos)
return et.parse(f)
def trade_spider():
os.chdir(r"F:\04_Independent Auditors Report")
with stdout2file("auditfeesexpenses.txt"):
for file in glob.iglob('**/*.html', recursive=True):
xml = skip_to(file, "<?xml")
tree = xml.getroot()
nsmap = {"ix": tree.nsmap["ix"]}
fractions = xml.xpath("//ix:nonFraction[contains(@name, 'AuditFeesExpenses')]", namespaces=nsmap)
for fraction in fractions:
print(file.split(os.path.sep)[-1], end="| ")
print(fraction.get("name"), end="| ")
print(fraction.text, end=" \n")
break
trade_spider()
ich diese Fehlermeldung:
Traceback (most recent call last):
File "C:/Users/6930p/PycharmProjects/untitled/Versuch/lxmlparser.py", line 43, in <module>
trade_spider()
File "C:/Users/6930p/PycharmProjects/untitled/Versuch/lxmlparser.py", line 33, in trade_spider
xml = skip_to(file, "<?xml")
File "C:/Users/6930p/PycharmProjects/untitled/Versuch/lxmlparser.py", line 26, in skip_to
return et.parse(f)
File "lxml.etree.pyx", line 3427, in lxml.etree.parse (src\lxml\lxml.etree.c:79720)
File "parser.pxi", line 1803, in lxml.etree._parseDocument (src\lxml\lxml.etree.c:116182)
File "parser.pxi", line 1823, in lxml.etree._parseFilelikeDocument (src\lxml\lxml.etree.c:116474)
File "parser.pxi", line 1718, in lxml.etree._parseDocFromFilelike (src\lxml\lxml.etree.c:115235)
File "parser.pxi", line 1139, in lxml.etree._BaseParser._parseDocFromFilelike (src\lxml\lxml.etree.c:110109)
File "parser.pxi", line 573, in lxml.etree._ParserContext._handleParseResultDoc (src\lxml\lxml.etree.c:103323)
File "parser.pxi", line 679, in lxml.etree._handleParseResult (src\lxml\lxml.etree.c:104936)
File "lxml.etree.pyx", line 324, in lxml.etree._ExceptionContext._raise_if_stored (src\lxml\lxml.etree.c:10656)
File "parser.pxi", line 362, in lxml.etree._FileReaderContext.copyToBuffer (src\lxml\lxml.etree.c:100828)
File "C:\Users\6930p\Anaconda3\lib\encodings\cp1252.py", line 23, in decode
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 1789: character maps to <undefined>
Mit lxml selbst den schnellsten Ansatz sein, fügen Sie eine Probe von Ihre Daten –
@PadraicCunningham: Bearbeitete OP mit einer Probe. Dies ist jedoch nur ein sehr kurzer Abschnitt, die ursprünglichen HTML-Dateien enthalten bis zu 3000 Zeilen .... –
Was möchten Sie analysieren?Gibt es auch Namespaces? –