BeautifulSoup: Große HTML Zweige parsen
Verfasst: Dienstag 25. Dezember 2012, 18:09
Hallo,
da ich mich zur Zeit in Sachen XML-Parsing etwas weiterbilden möchte (ich hab das Thema früher immer gemieden), versuche ich zur Zeit eine HTML-Kopie meiner Facebook-Nachrichten (es ist möglich, eine Kopie deiner Facebook-Daten als Archiv herunterzuladen) zu parsen. Alle Nachrichten, die ich je auf Facebook verschickt habe sind in dieser Datei enthalten - dementsprechend ist die Datei etwa 10MB groß.
Der Aufbau einer Unterhaltung sieht dort in etwa so aus:
So wie ich das sehe, müsste sich das doch eigentlich ganz nett parsen lassen, oder? Mein derzeitiger Ansatz sind folgende Funktionen (,welche allerdings erstaunlich langsam sind):
Was mich allerdings an der ganzen Sache stört, ist dass es furchtbar lange dauert die Html-Datei zu parsen. Ich bin jetzt wirklich keiner, der ständig nur am optimieren ist, aber ich denke, dass man das bestimmt schneller parsen kann. Zur Zeit benötigt die Funktion process_threads(htmlsource) bei einer 13MB großen Datei etwa 75 Sekunden. Ich jemand Optimierungsvorschläge? Vielleicht gehe ich beim parsen auch ganz "falsch" vor. Vielleicht sollte ich nicht die ganze zeit .find(...) benutzen.
da ich mich zur Zeit in Sachen XML-Parsing etwas weiterbilden möchte (ich hab das Thema früher immer gemieden), versuche ich zur Zeit eine HTML-Kopie meiner Facebook-Nachrichten (es ist möglich, eine Kopie deiner Facebook-Daten als Archiv herunterzuladen) zu parsen. Alle Nachrichten, die ich je auf Facebook verschickt habe sind in dieser Datei enthalten - dementsprechend ist die Datei etwa 10MB groß.
Der Aufbau einer Unterhaltung sieht dort in etwa so aus:
Code: Alles auswählen
<div class="thread"><div class="border">
<div class="header">
<span class="profile fn">Chatpartner1</span>, <span class="profile fn">Chatpartner 2</span> <!-- ggf. noch mehr !-->
<abbr class="time published" title="2012-12-15T23:31:17+0000">15. Dezember 2012 um 16:31</abbr> <!-- Datum des letzten Kontakts !-->
</div>
<!-- Selbsterklärend !-->
<div class="message">
<div class="from"><span class="profile fn">Name Absender</span></div>
<abbr class="time published" title="2010-09-18T09:17:53+0000">18. September 2010 um 3:17</abbr>
<div class="msgbody">
NACHRICHT
</div>
</div>
<div class="message">
<div class="from"><span class="profile fn">Name Absender</span></div>
<abbr class="time published" title="2010-09-18T09:17:53+0000">18. September 2010 um 3:17</abbr>
<div class="msgbody">
NACHRICHT
</div>
</div>
<!-- weitere Nachrichten !-->
</div></div>
Code: Alles auswählen
def process_threads(html_source):
data = []
print "[*] Initializing soup..."
soup = BeautifulSoup(html_source) # dauert sehr lange!
print "[*] Intialized soup!"
threads = soup.find_all("div", {"class" : "border"})
print "[*] Processing threads..."
for thread in threads:
data.append(process_thread(thread))
print "[*] Threads created"
return data
def process_thread(thread):
data = {"messages" : []}
# Get partners name
header = thread.find("div", {"class" : "header"})
partners = header.find_all("span", {"class" :
"profile fn"})
data["partners"] = frozenset(map(lambda obj: obj.getText(), partners))
# Get last contact
last_contact = header.find("abbr", {"class" :
"time published"})
data["last contact"] = datetime.datetime.strptime(last_contact.get("title"),
"%Y-%m-%dT%H:%M:%S+0000")
# Extract messages
messages = thread.find_all("div", {"class" : "message"})
for message in messages:
msg = {}
msg["from"] = message.find("span", {"class" : "profile fn"}).getText()
msg["time"] = datetime.datetime.strptime(message.find("abbr").get("title"),
"%Y-%m-%dT%H:%M:%S+0000")
msg["text"] = message.find("div", {"class" : "msgbody"}).getText()
data["messages"].append(msg)
return data