2016-05-10 4 views
1

ich mit diesem Kodex arbeite:Schönes Suppe 4 HTML Dokumente Verzeichnis

from bs4 import BeautifulSoup 
import glob 
import os 
import re 

def trade_spider(): 
    os.chdir(r"C:\Users\6930p\FLO'S DATEIEN\Master FAU\Sommersemester 2016\02_Masterarbeit\04_Testumgebung\01_Probedateien für Analyseaspekt\Independent Auditors Report") 
    for file in glob.glob('*.html'): 
     with open(file, encoding="utf8") as f: 
      contents = f.read() 
      soup = BeautifulSoup(contents, "html.parser") 
      results = [item for item in soup.findAll("ix:nonfraction") if re.match("^[^:]:AuditFeesExpenses", item['name'])] 
      print(results) 
       #print(file, end="| ") 
       #print(item['name'], end="| ") 
       #print(item.get_text()) 
trade_spider() 

ich mehr HTML-Dokumente in einem bestimmten Verzeichnis auf meinem Computer mit BS4 zu analysieren versuchen. Mein Ziel ist es, Tags zu finden, die mit "ix: NonFraction ...." beginnen und ein name-Attribut enthalten, das vor 'AuditFeesExpenses' mehrere Ausdrücke haben kann, wie name = "aurep: AuditFeesExpenses, name = bus: AuditFeesExpenses" usw. verwende eine RegEx). Also, wenn BS4 diesen bestimmten Tag gefunden hat, möchte ich den Text mit suppe.get_text (Value) daraus extrahieren.

Wer eine Idee, was ich verpasst habe?

UPDATE: Ein Beispiel-Tag wäre:

<td style=" width:12.50%; text-align:right; " class="ta_60"> 
<ix:nonFraction contextRef="ThirdPartyAgentsHypercube_FY_31_12_2012_Set1" 
name="ns19:AuditFeesExpenses" unitRef="GBP" decimals="0" 
format="ixt2:numdotdecimal" scale="0" xmlns:ix="http://www.xbrl.org 
/2008/inlineXBRL">3,600</ix:nonFraction></td> 

Normalerweise erscheint dieser Tag in einer Linie aus Gründen der Übersichtlichkeit ich ein paar neue Zeilen eingefügt!

Mein abschließender-Code sieht wie folgt aus:

from bs4 import BeautifulSoup 
import glob 
import os 
import re 

def trade_spider(): 
    os.chdir(r"C:\Users\6930p\FLO'S DATEIEN\Master FAU\Sommersemester 2016\02_Masterarbeit\04_Testumgebung\01_Probedateien für Analyseaspekt\Independent Auditors Report") 
    for file in glob.glob('*.html'): 
     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(".*AuditFeesExpenses", item['name']): 
        print(file, end="| ") 
        print(item['name'], end="| ") 
        print(item.get_text()) 
trade_spider() 

und gibt mir diese Ausgabe:

Prod224_0010_00079350_20140331.html | uk-aurep: AuditBeträge | 2000

Antwort

0

Die findAll()-Funktion hat name als ihren ersten Parameter. Wenn Sie anrufen

`soup.findAll('ix:NonFraction', name=re.compile("^[^:]:AuditFeesExpenses"))`, 

Sie effektiv fordern soup mit dem Parameter name=ix:NonFractionUNDname=re.compile("^[^:]:AuditFeesExpenses"). Natürlich können wir name nur auf einen dieser beiden Eingänge setzen, was den Fehler ergibt.

Die Fehlermeldung zeigt find_all() anstelle von findAll(). Aus der docs, sehen wir, dass findAll der alte Methodenname find_all ist. Die find_all Methode sollte verwendet werden.

Die Verwirrung kann von dem Attribut name kommen. Es ist wichtig, zwischen dem BeautifulSoup-Attribut name und dem HTML-Attribut name zu unterscheiden. Um zu demonstrieren, gehe ich davon aus, dass ein Tag mit diesem Format hat:

<body> 
    <ix:NonFraction name="AuditFeesExpenses">stuff<ix:NonFraction> 
</body> 

Wir können alle <ix:NonFraction> Tags mit soup.find_all("ix:nonfraction") finden. Das gibt die folgende Liste enthält die Ergebnisse:

[<ix:NonFraction name="AuditFeesExpenses">stuff<ix:NonFraction>] 

Iterate durch diese Ein-Posten-Liste die beiden verschiedenen Namen Attribute zu sehen.Zuerst greifen wir das BeautifulSoup Namensattribut als Attribut des Objekts:

for item in soup.find_all("ix:nonfraction"): 
    print(item.name) 

Out: 'ix:nonfraction' 

das HTML-Namensattribut zu sehen, den Zugang name als Wörterbuch-Schlüssel:

for item in soup.find_all("ix:nonfraction"): 
    print(item['name']) 

Out: 'AuditFeesExpenses' 

der Suche Mitglied werden beide zusammen verengen die Ergebnisse nach unten:

results = [item for item in soup.find_all("ix:nonfraction") if re.match("^[^:]:AuditFeesExpenses", item['name']) 

Out: [<ix:nonfraction name="ns19:AuditFeesExpenses">3,600</ix:nonfraction>] 

Oder, wenn wir den Text jedes Spiel erhalten möchten:

results = [item.get_text() for item in soup.find_all("ix:nonfraction") if re.match("^[^:]:AuditFeesExpenses", item['name']) 

Out: [3,600] 

Vorgeschlagene Code für die vollständige Ausgabe:

from bs4 import BeautifulSoup 
import glob 
import os 

def trade_spider(): 
    os.chdir(r"C:\Independent Auditors Report") 
    for file in glob.glob('*.html'): 
     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("^[^:]:AuditFeesExpenses", item['name']) 
        print(file, end="| ") 
        print(item['name'], end="| ") 
        print(item.get_text()) 
trade_spider() 
+0

ich meine Frage aktualisiert, so dass Sie einen Beispiel-Tag sehen können, dass ich für meinen Code –

+0

aktualisiert Antwort zu verwenden versuchen. Ich denke, das Problem rührt von 2 verschiedenen 'name'-Attributen her. Die endgültige Lösung kann 2 Schritte erfordern: alle "NonFraction" -Tags erhalten, dann filtern, um alle "AuditFeesExpenses" -Namen zu erhalten. – SNygard

+0

Das funktioniert fast perfekt, aber Python druckt jetzt jeden NonFraction-Tag-Namen im Dokument (~ 100-200 für jedes Dokument). Gibt es eine Chance, nur nach den "AuditFeesExpenses" zu filtern und gleichzeitig Python mitzuteilen, dass der Text zwischen den Tags> 3.600