2015-10-22 6 views
6

Próbuję zeskrobać strony za pomocą BeatifulSoupZeskrobać tylko tekst, w obrębie elementu HTML, który ma klasę, używając piękny zupę

import urllib2 
from bs4 import BeautifulSoup 

url='http://www.xpn.org/playlists/xpn-playlist' 
page = urllib2.urlopen(url) 

soup = BeautifulSoup(page.read()) 

for link in soup.find_all("li", class_="song"): 
    print link 

Problemem jest tekst chciałbym wrócić nie jest zamknięty w jego własnym znaczniku html

<li class="song"> <a href="/default.htm" onclick="return clickreturnvalue() 
" onmouseout="delayhidemenu()" onmouseover="dropdownmenu(this, event, menu1, 
'100px','Death Vessel','Mandan Dink','Stay Close')">Buy</a> 
Chuck Ragan - Rotterdam - Folkadelphia Session</li> 

Co chcę powrócić Chuck Ragan - Rotterdam - Folkadelphia Session

bonusowe punkty: dane zwrócone jest w formacie artysty/utworu/A lbum. Jaka byłaby właściwa struktura danych do przechowywania i manipulowania tymi informacjami?

Odpowiedz

1

Spróbuj czegoś takiego:

for link in soup.find_all("li", class_="song"): 
    print link.text 

wyjściowa:

Buy Chuck Ragan - Rotterdam - Folkadelphia Session 

Oczywiście, jeśli chcesz usunąć Buy, można użyć slice tak:

for link in soup.find_all("li", class_="song"): 
    print link.text.strip()[5:] 

Wyjście jest :

Chuck Ragan - Rotterdam - Folkadelphia Session 

Jeśli chcesz zapisać te ciąg na liście:

[i.strip() for i in link.text.strip()[5:].split('-')] 

wyjściowa:

['Chuck Ragan', 'Rotterdam', 'Folkadelphia Session'] 

Aby uzyskać więcej informacji, można sprawdzić document.

+0

Dzięki człowiek! Jak dokładnie działa [5:]? –

+1

To usunie pierwsze 5 znaków. zobacz [to pytanie] (http://stackoverflow.com/questions/509211/explain-pythons-slice-notation). –

+0

I około * Jaka byłaby właściwa struktura danych do przechowywania i manipulowania tymi informacjami? *, Może wykorzystywać bazę danych? –

0

Można użyć czegoś takiego.

for l in soup.find_all("li", class_="song"): 
    album = l.text.split("-")[2] 
    song = l.text.split("-")[1] 
    artist = l.text.split("-")[0].split(" ")[1] 
1

Oto inny sposób! (Zakładając li ma 3 dzieci Jeśli nie, zmień [2] do [1].):

>>> html = '''<li class="song"> <a href="/default.htm" onclick="return clickreturnvalue() 
... " onmouseout="delayhidemenu()" onmouseover="dropdownmenu(this, event, menu1, 
... '100px','Death Vessel','Mandan Dink','Stay Close')">Buy</a> 
... Chuck Ragan - Rotterdam - Folkadelphia Session</li>''' 

>>> from bs4 import BeautifulSoup as bs 
>>> all_li = soup.findAll('li', class_='song') 
>>> for li in all_li: 
...  text = list(li.children)[2] 
...  artist, song, album = text.split('-') 
...  print artist, song, album 
Chuck Ragan Rotterdam Folkadelphia Session 
+0

Próbowałem tego rozwiązania, ale dostałem błąd '----> 9 all_li = soup.findall ('li', class _ = 'song') '' TypeError: 'Obiekt NoneType' nie jest możliwy do wywołania ' –

+0

Zauważ, że' soup.findAll() 'i' soup.findall() 'są różnymi funkcjami! Ten, którego szukamy, to 'soup.findAll()', którego nie wypróbowałeś :-) –

+0

Ah! Dziękuję Ci!! –

0

** Skończyło się przy użyciu named tuple do składowania **

from bs4 import BeautifulSoup 
import urllib2 
from collections import namedtuple 

url='http://www.xpn.org/playlists/xpn-playlist' 
page = urllib2.urlopen(url) 


soup = BeautifulSoup(page.read()) 

songs=[] 
Song = namedtuple("Song", "artist name album") 
for link in soup.find_all("li", class_="song"): 
    song = Song._make(link.text.strip()[12:].split(" - ")) 
    songs.append(song) 

for song in songs: 
    print(song.artist, song.name, song.album)