python - 使用 lxml 解析 XML 时出现问题

标签 python xml pandas lxml lxml.objectify

我一直在尝试将 XML 提要解析为 Pandas 数据帧,但无法找出哪里出错了。

import pandas as pd
import requests
import lxml.objectify
path = "http://www2.cineworld.co.uk/syndication/listings.xml"

xml = lxml.objectify.parse(path)
root = xml.getroot()

下一段代码是解析我想要的位并创建一个显示字典列表。

shows_list = []
for r in root.cinema:
    rec = {}
    rec['name'] = r.attrib['name']
    rec['info'] = r.attrib["root"] + r.attrib['url']
    listing = r.find("listing")
    for f in listing.film:
        film = rec
        film['title'] = f.attrib['title']
        film['rating'] = f.attrib['rating']
        shows = f.find("shows")
        for s in shows['show']:
            show = rec
            show['time'] = s.attrib['time']
            show['url'] = s.attrib['url']
            #print show
            shows_list.append(rec)

df = pd.DataFrame(show_list)

当我运行代码时,电影和时间字段似乎在行内复制了多次。但是,如果我将 print 语句放入代码中(已被注释掉),则字典将显示为我所期望的。

我做错了什么?如果有更 Python 的方式来执行解析过程,请随时告诉我。

编辑:澄清一下:

如果我使用 print 语句来检查循环时发生的情况,这些是数据的最后五行。

{'info': 'http://cineworld.co.uk/cinemas/107/information', 'rating': 'TBC', 'name': 'Cineworld Stoke-on-Trent', 'title': "Dad's Army", 'url': '/booking?performance=4729365&seats=STANDARD', 'time': '2016-02-07T20:45:00'}
{'info': 'http://cineworld.co.uk/cinemas/107/information', 'rating': 'TBC', 'name': 'Cineworld Stoke-on-Trent', 'title': "Dad's Army", 'url': '/booking?performance=4729366&seats=STANDARD', 'time': '2016-02-08T20:45:00'}
{'info': 'http://cineworld.co.uk/cinemas/107/information', 'rating': 'TBC', 'name': 'Cineworld Stoke-on-Trent', 'title': "Dad's Army", 'url': '/booking?performance=4729367&seats=STANDARD', 'time': '2016-02-09T20:45:00'}
{'info': 'http://cineworld.co.uk/cinemas/107/information', 'rating': 'TBC', 'name': 'Cineworld Stoke-on-Trent', 'title': "Dad's Army", 'url': '/booking?performance=4729368&seats=STANDARD', 'time': '2016-02-10T20:45:00'}
{'info': 'http://cineworld.co.uk/cinemas/107/information', 'rating': 'TBC', 'name': 'Cineworld Stoke-on-Trent', 'title': "Dad's Army", 'url': '/booking?performance=4729369&seats=STANDARD', 'time': '2016-02-11T20:45:00'}
{'info': 'http://cineworld.co.uk/cinemas/107/information', 'rating': 'PG', 'name': 'Cineworld Stoke-on-Trent', 'title': 'Autism Friendly Screening - Goosebumps', 'url': '/booking?performance=4782937&seats=STANDARD', 'time': '2016-02-07T11:00:00'}

这是列表的结尾: ...

{'info': 'http://cineworld.co.uk/cinemas/107/information',
  'name': 'Cineworld Stoke-on-Trent',
  'rating': 'PG',
  'time': '2016-02-07T11:00:00',
  'title': 'Autism Friendly Screening - Goosebumps',
  'url': '/booking?performance=4782937&seats=STANDARD'},
 {'info': 'http://cineworld.co.uk/cinemas/107/information',
  'name': 'Cineworld Stoke-on-Trent',
  'rating': 'PG',
  'time': '2016-02-07T11:00:00',
  'title': 'Autism Friendly Screening - Goosebumps',
  'url': '/booking?performance=4782937&seats=STANDARD'},
 {'info': 'http://cineworld.co.uk/cinemas/107/information',
  'name': 'Cineworld Stoke-on-Trent',
  'rating': 'PG',
  'time': '2016-02-07T11:00:00',
  'title': 'Autism Friendly Screening - Goosebumps',
  'url': '/booking?performance=4782937&seats=STANDARD'},
 {'info': 'http://cineworld.co.uk/cinemas/107/information',
  'name': 'Cineworld Stoke-on-Trent',
  'rating': 'PG',
  'time': '2016-02-07T11:00:00',
  'title': 'Autism Friendly Screening - Goosebumps',
  'url': '/booking?performance=4782937&seats=STANDARD'}]

最佳答案

您的代码只有一个不断更新的对象:rec。试试这个:

from copy import copy
shows_list = []
for r in root.cinema:
    rec = {}
    rec['name'] = r.attrib['name']
    rec['info'] = r.attrib["root"] + r.attrib['url']
    listing = r.find("listing")
    for f in listing.film:
        film = copy(rec) # New object
        film['title'] = f.attrib['title']
        film['rating'] = f.attrib['rating']
        shows = f.find("shows")
        for s in shows['show']:
            show = copy(film) # New object, changed reference
            show['time'] = s.attrib['time']
            show['url'] = s.attrib['url']
            #print show
            shows_list.append(show) # Changed reference

df = pd.DataFrame(show_list)

通过这种结构,将rec中的数据复制到每个film中,并将每个film中的数据复制到每个中>显示。然后,最后将 show 添加到 shows_list 中。

您可能想阅读this article了解有关 film = rec 行中发生的情况的更多信息,即您为原始字典指定另一个名称,而不是创建一个新字典。

关于python - 使用 lxml 解析 XML 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34880524/

相关文章:

python - 尝试将 3 个列表中的元素组合(连接)为一个新列表

java - 从 jar 文件运行 python 脚本

java - Xslt Saxon 处理器 - 目录中的所有文件

xml - 在 SVG 中对齐文本

python - 如何使用 python pandas 清理多种格式的日期范围?

python - 使用 Postgres 在 Python 中用单引号形成插入语句

html - 查找 XPATH 表达式

python - 如何从数据框字典创建 Pandas DataFrame?

python - 在一个图中叠加两个密度

python - deepcopy 不尊重元类