2016-07-21 6 views
2

Ich benutze Beutifulsoup 4 und Python 3.5+, um Webdata zu extrahieren. Ich habe folgende html, aus dem ich zu extrahieren bin:Mit Beautifulsoup, extrahiere Tags des Elements außer den angegebenen

<div class="the-one-i-want"> 
    <p> 
     content 
    </p> 
    <p> 
     content 
    </p> 
    <p> 
     content 
    </p> 
    <p> 
     content 
    </p> 
    <ol> 
     <li> 
      list item 
     </li> 
     <li> 
      list item 
     </li> 
    </ol> 
    <div class='something-i-don't-want> 
     content 
    </div> 
    <script class="something-else-i-dont-want'> 
     script 
    </script> 
    <p> 
     content 
    </p> 
</div> 

Alle Inhalte, die ich extrahieren möchten im <div class="the-one-i-want"> Element gefunden wird. Gerade jetzt, ich bin die folgenden Methoden verwenden, die die meiste Zeit arbeiten:

soup = Beautifulsoup(html.text, 'lxml') 
content = soup.find('div', class_='the-one-i-want').findAll('p') 

Dies schließt Skripte, seltsam Einsatz div ‚s und sonst un-vorhersehbare Inhalte wie Anzeigen oder empfohlenen Inhalt 'Typ Zeug .

Nun gibt es einige Instanzen, in denen andere Elemente als nur die Tags <p> vorhanden sind, die inhaltlich für den Hauptinhalt wie Listen relevant sind.

Gibt es eine Möglichkeit, den Inhalt von den <div class="the-one-i-want"> in einer Art und Weise als solche zu erhalten:

soup = Beautifulsoup(html.text, 'lxml') 
content = soup.find('div', class_='the-one-i-want').findAll(desired-content-elements) 

Wo desired-content-elements wäre inklusive jedes Element, dass ich fit für diesen bestimmten Inhalt als? Wie zum Beispiel alle <p> Tags, alle <ol> und <li> Tags, aber keine <div> oder <script> Tags.

Vielleicht bemerkenswert, ist meine Methode, den Inhalt zu speichern:

content_string = '' 
for p in content: 
    content_string += str(p) 

Dieser Ansatz sammelt die Daten, in der Reihenfolge des Auftretens, die als schwierig erweisen würde, zu verwalten, wenn ich einfach verschiedene Elementtypen durch verschiedene Iterationsprozesse gefunden . Ich möchte NICHT die Re-Konstruktion von Split-Listen verwalten, um die Reihenfolge wieder herzustellen, in der jedes Element ursprünglich im Inhalt auftrat, wenn möglich.

Antwort

1

Sie können eine Liste von Tags übergeben, die Sie wollen:

content = soup.find('div', class_='the-one-i-want').find_all(["p", "ol", "whatever"]) 

Wenn wir etwas ähnliches auf Ihrer Frage url laufen für p und Pre-Tags suchen, können Sie sehen, wir beide bekommen:

...: for ele in soup.select_one("td.postcell").find_all(["pre","p"]): 
    ...:  print(ele) 
    ...: 

<p>I'm using Beutifulsoup 4 and Python 3.5+ to extract webdata. I have the following html, from which I am extracting:</p> 
<pre><code>&lt;div class="the-one-i-want"&gt; 
    &lt;p&gt; 
     content 
    &lt;/p&gt; 
    &lt;p&gt; 
     content 
    &lt;/p&gt; 
    &lt;p&gt; 
     content 
    &lt;/p&gt; 
    &lt;p&gt; 
     content 
    &lt;/p&gt; 
    &lt;ol&gt; 
     &lt;li&gt; 
      list item 
     &lt;/li&gt; 
     &lt;li&gt; 
      list item 
     &lt;/li&gt; 
    &lt;/ol&gt; 
    &lt;div class='something-i-don't-want&gt; 
     content 
    &lt;/div&gt; 
    &lt;script class="something-else-i-dont-want'&gt; 
     script 
    &lt;/script&gt; 
    &lt;p&gt; 
     content 
    &lt;/p&gt; 
&lt;/div&gt; 
</code></pre> 
<p>All of the content that I want to extract is found within the <code>&lt;div class="the-one-i-want"&gt;</code> element. Right now, I'm using the following methods, which work most of the time:</p> 
<pre><code>soup = Beautifulsoup(html.text, 'lxml') 
content = soup.find('div', class_='the-one-i-want').findAll('p') 
</code></pre> 
<p>This excludes scripts, weird insert <code>div</code>'s and otherwise un-predictable content such as ads or 'recommended content' type stuff.</p> 
<p>Now, there are some instances in which there are elements other than just the <code>&lt;p&gt;</code> tags, which has content that is contextually important to the main content, such as lists.</p> 
<p>Is there a way to get the content from the <code>&lt;div class="the-one-i-want"&gt;</code> in a manner as such:</p> 
<pre><code>soup = Beautifulsoup(html.text, 'lxml') 
content = soup.find('div', class_='the-one-i-want').findAll(desired-content-elements) 
</code></pre> 
<p>Where <code>desired-content-elements</code>would be inclusive of every element that I deemed fit for that particular content? Such as, all <code>&lt;p&gt;</code> tags, all <code>&lt;ol&gt;</code> and <code>&lt;li&gt;</code> tags, but no <code>&lt;div&gt;</code> or <code>&lt;script&gt;</code> tags.</p> 
<p>Perhaps noteworthy, is my method of saving the content:</p> 
<pre><code>content_string = '' 
for p in content: 
    content_string += str(p) 
</code></pre> 
<p>This approach collects the data, in order of occurrence, which would prove difficult to manage if I simply found different element types through different iteration processes. I'm looking to NOT have to manage re-construction of split lists to re-assemble the order in which each element originally occurred in the content, if possible.</p> 
+0

Funktioniert wie ein Charme, danke für Ihre Hilfe @padraic – theeastcoastwest

-1

Funktioniert das für Sie? Es sollte den Inhalt durchgehen und den gewünschten Text hinzufügen, während die Tags div und script ignoriert werden.

for p in content: 
    if p.find('div') or p.find('script'): 
     continue 
    content_string += str(p) 
0

Sie können das tun ganz einfach mit

soup = Beautifulsoup(html.text, 'lxml') 
desired-tags = {'div', 'ol'} # add what you need 
content = filter(lambda x: x.name in desired-tags 
     soup.find('div', class_='the-one-i-want').children) 

Dies wird durch alle direkten Kinder der div Tag gehen. Wenn Sie möchten, dass dies rekursiv geschieht (Sie haben etwas über das Hinzufügen von li Tags gesagt), sollten Sie .decendants anstelle von .children verwenden. Glückliches Krabbeln!