2012-04-28 2 views
1

У меня есть этот XML-файл:Итерация файл XML и извлечения данных из него

<movie id = 0> 
    <Movie_name>The Shawshank Redemption </Movie_name> 
    <Address>http://www.imdb.com/title/tt0111161/ 
    </Address> 
    <year>1994 </year> 
    <stars>Tim Robbins Morgan Freeman Bob Gunton </stars> 
    <plot> plot... 
    </plot> 
    <keywords>Reviews, Showtimes</keywords> 
</movie> 

<movie id = 1> 
    <Movie_name>Inglourious Basterds </Movie_name> 
    <Address>http://www.imdb.com/title/tt0361748/ 
    </Address> 
    <year>2009 </year> 
    <stars>Brad Pitt M&#xE9;lanie Laurent Christoph Waltz </stars> 
    <plot>plot/... 
    </plot> 
    <keywords>Reviews, credits </keywords> 
</movie> 

Как итерацию файл извлечения для каждого фильма его speciffic данных? Я имею в виду для фильма 0: его имя, адрес, год и так далее.

Структура входного файла является обязательной, поэтому извлечение данных можно выполнить во время цикла.

Большое спасибо.

ответ

3

EDIT - брать на борт улучшенный ввод XML

Я настоятельно рекомендую пытаться подтвердить свой вклад как в замечанием @Lattyware. Я нахожу, что с недопустимым XML и HTML, BeautifulSoup отлично справляется с восстановлением чего-то полезного. Вот то, что он делает с быстрой попытки:

from BeautifulSoup import BeautifulSoup 

# Note: I have added the <movielist> root element 
xml = """<movielist> 
<movie id = 0> 
    <Movie_name>The Shawshank Redemption </Movie_name> 
    <Address>http://www.imdb.com/title/tt0111161/ 
    </Address> 
    <year>1994 </year> 
    <stars>Tim Robbins Morgan Freeman Bob Gunton </stars> 
    <plot> plot... 
    </plot> 
    <keywords>Reviews, Showtimes</keywords> 
</movieNum> 

<movie id = 1> 
    <Movie_name>Inglourious Basterds </Movie_name> 
    <Address>http://www.imdb.com/title/tt0361748/ 
    </Address> 
    <year>2009 </year> 
    <stars>Brad Pitt M&#xE9;lanie Laurent Christoph Waltz </stars> 
    <plot>plot/... 
    </plot> 
    <keywords>Reviews, credits </keywords> 
</movieNum> 

</movielist>""" 

soup = BeautifulSoup(xml) 
movies = soup.findAll('movie') 

for movie in movies: 
    id_tag = movie['id'] 
    name = movie.find("movie_name").text 
    url = movie.find("address").text 
    year = movie.find("year").text 
    stars = movie.find("stars").text 
    plot = movie.find("plot").text 
    keywords = movie.find("keywords").text 
    for item in (id_tag, name, url, year, stars, plot, keywords): 
     print item 
    print '=' * 50 

Этот вывод будет следующим (ИД-тег теперь доступен):

0 
The Shawshank Redemption 
http://www.imdb.com/title/tt0111161/ 
1994 
Tim Robbins Morgan Freeman Bob Gunton 
plot... 
Reviews, Showtimes 
================================================== 
1 
Inglourious Basterds 
http://www.imdb.com/title/tt0361748/ 
2009 
Brad Pitt M&#xE9;lanie Laurent Christoph Waltz 
plot/... 
Reviews, credits 
================================================== 

Это, надеюсь, дает старт ... Это может только отсюда лучше.

3

Вы хотите проверить xml.etree.ElementTree.

Я бы также отметить, что у вас там не действует XML, так что вы можете столкнуться с проблемами. Действительный XML будет выглядеть примерно так:

<movie id="0"> 
    <name>The Shawshank Redemption</name> 
    <url>http://www.imdb.com/title/tt0111161/</url> 
    <year>1994</year> 
    <stars> 
    <star>Tim Robbins</star> 
    <star>Morgan Freeman</star> 
    <star>Bob Gunton</star> 
    </stars> 
    <plot>plot...</plot> 
    <keywords> 
    <keyword>Reviews</keyword> 
    <keyword>Showtimes</keyword> 
    </keywords> 
</movie> 

Обратите внимание на нижний регистр имен тегов и атрибутов (<movieNum = 0> не имеет смысла). Вам также потребуется объявление XML (например, <?xml version="1.0" encoding="UTF-8" ?>) вверху. Вы можете проверить свой XML на XML Validation или использовать, например, xmllint.

Как только у вас есть действительный XML, вы можете его проанализировать и перебрать по нему с помощью iterparse() или проанализировать его, а затем выполнить итерацию по построенному дереву элементов.

2

The BeutifulSoup более прощает, и его также можно использовать для HTML (где некоторые закрывающие теги являются необязательными). ElementTree может использоваться только в том случае, если XML действителен. Вы можете сделать это частично действительным, обернув фрагмент одному элементу. Значения атрибутов должны быть заключены в кавычки. Попробуйте следующий подход, в котором был создан класс Movie, чтобы захватить информацию от одного фильма. Класс выводится из dict так же гибко, как и dict; Однако, вы можете создавать свои собственные методы для возврата обработанных значений из собранной информации:

# -*- coding: utf-8 -*- 
import xml.etree.ElementTree as ET 

class Movie(dict): 

    def __init__(self, movie_element): 
     assert movie_element.tag == 'movie' # we are able to process only that 
     self['id'] = movie_element.attrib['id'] 
     for e in movie_element: 
      self[e.tag] = e.text.strip() 

    def name(self): 
     return self['Movie_name'] 

    def url(self): 
     return self['Address'] 

    def year(self): 
     return self['year']  

    def stars(self): 
     return self['stars'] 

    def plot(self): 
     return self['plot'] 

    def keywords(self): 
     return self['keywords'] 

    def __str__(self): 
     lst = [] 
     lst.append(self.name() + ' (' + self.year() + ')') 
     lst.append(self.stars()) 
     lst.append(self.url()) 
     return '\n'.join(lst) 


fragment = '''\ 
<movie id = "0"> 
    <Movie_name>The Shawshank Redemption </Movie_name> 
    <Address>http://www.imdb.com/title/tt0111161/ 
    </Address> 
    <year>1994 </year> 
    <stars>Tim Robbins Morgan Freeman Bob Gunton </stars> 
    <plot> plot... 
    </plot> 
    <keywords>Reviews, Showtimes</keywords> 
</movie> 

<movie id = "1"> 
    <Movie_name>Inglourious Basterds </Movie_name> 
    <Address>http://www.imdb.com/title/tt0361748/ 
    </Address> 
    <year>2009 </year> 
    <stars>Brad Pitt Melanie Laurent Christoph Waltz </stars> 
    <plot>plot/... 
    </plot> 
    <keywords>Reviews, credits </keywords> 
</movie> 
''' 

fixed_fragment = '<root>\n' + fragment + '</root>' 
##print fixed_fragment 

tree = ET.fromstring(fixed_fragment) 
movies = [] 
for m in tree: 
    movies.append(Movie(m)) 

for movie in movies: 
    print '\n------------------' 
    print movie  

Он печатает на моей консоли:

------------------ 
The Shawshank Redemption (1994) 
Tim Robbins Morgan Freeman Bob Gunton 
http://www.imdb.com/title/tt0111161/ 

------------------ 
Inglourious Basterds (2009) 
Brad Pitt Melanie Laurent Christoph Waltz 
http://www.imdb.com/title/tt0361748/ 

Обратите внимание, что я заменил символы не-ASCII - проблема с кодировкой должна решаться отдельно.

Смежные вопросы