【问题标题】:Parsing xml file with regex: expected string or buffer使用正则表达式解析 xml 文件:预期的字符串或缓冲区
【发布时间】:2015-12-22 23:39:37
【问题描述】:

我正在尝试使用正则表达式从 xml 文件中获取一些数据(我知道我应该适当地使用一些 xml 解析器,但是如果您之前没有使用过任何 xml 解析器,正则表达式似乎更简单)

这是我的python代码:

import datetime,re
date= datetime.datetime.today().strftime('%Y%m%d')

output = open(r'C:\Users\Peter\AppData\Roaming\Kodi\addons\plugin.video.videoaddon\resources\epg.xml', 'r')
match = re.compile('start="%s(.+?)\s.+?".+?channel="Bravo (US)"\s><title>(.+?)</title>'%(date)).findall(output)
for start,title in match:
    print(start,title)

我收到TypeError: Expected string or buffer

谁能解释我为什么会收到这个错误?

如果有人感兴趣,我正在尝试做的其他信息:

XML 文件示例:http://pastebin.com/9yC1FTYu 我知道这个 xml 格式不正确,但这就是我从软件 API 中获取它的方式。

基本上我需要得到: start 时间戳的最后一部分,第一部分必须匹配日期,以及 &lt;title&gt; 文本。我需要在channel 匹配Bravo (US) 的地方得到这些。

【问题讨论】:

  • XML 没有格式错误,为什么不使用合适的 XML 解析器呢?
  • 正如我所说,我从来没有使用过 xml 解析器的经验,我只是不知道该怎么做。正则表达式对我来说似乎更简单。

标签: python regex xml xml-parsing


【解决方案1】:

您需要使用read() 或其他方式读取文件,文件对象仅存储在输出变量中,而不是内容。

output = open(r'C:\Users\Peter\AppData\Roaming\Kodi\addons\plugin.video.videoaddon\resources\epg.xml', 'r').read()
                                                                                                              ^

【讨论】:

    【解决方案2】:

    您正在将 文件对象 传递给 pattern.findall() 方法。您必须先读取该文件:

    pattern = re.compile('start="%s(.+?)\s.+?".+?channel="Bravo (US)"\s><title>(.+?)</title>'%(date))
    filename = r'C:\Users\Peter\AppData\Roaming\Kodi\addons\plugin.video.videoaddon\resources\epg.xml'
    with open(filename, 'r') as xmlfile:
        match = pattern.findall(output.read())
    

    但是,您应该在此处真正使用 XML 解析器。标准库自带ElementTree API

    import xml.etree.ElementTree as ET
    
    filename = r'C:\Users\Peter\AppData\Roaming\Kodi\addons\plugin.video.videoaddon\resources\epg.xml'
    tree = ET.parse(filename)
    for programme in tree.findall(".//programme[@channel='Bravo (US)']"):
        showtime = programme.attrib['start']
        if showtime.startswith(date):
            print showtime[8:14], programme.find('title').text
    

    如果您安装了lxml,您可以使用更复杂的 XPath 查询,包括搜索日期的查询:

    import lxml.etree as ET
    
    filename = r'C:\Users\Peter\AppData\Roaming\Kodi\addons\plugin.video.videoaddon\resources\epg.xml'
    date_predicate = '[starts-with(@start, "{}")]'.format(date)
    tree = ET.parse(filename)
    for programme in tree.xpath('.//programme[@channel="Bravo (US)"]' + date_predicate):
        showtime = programme.attrib['start']
        print showtime[8:14], programme.find('title').text
    

    【讨论】:

    • 非常感谢,这个 ElementTree 似乎非常适合工作。我不能使用 lxml,因为我将在 kodi/xmbc 上运行 python 脚本,并且我只能使用来自原始 python 的库。我还有一个问题:我如何将时间戳的其他部分从开始标签转换为字符串?例如: start="20150925230000 +0300" ?所以我最终可以打印出节目开始时间和节目名称: print(starttime,title) 我真的很感谢你的帮助,再次感谢你!
    • @user2033139:您必须使用字符串操作来解析它; from datetime import timeshowtime = el.attrib['start']timestamp = time(int(showtime[8:10]), int(showtime[10:12]), int(showtime[12:14])) 会给你一个 datetime.time() 对象,其中只有时间部分(忽略时区)。
    猜你喜欢
    • 2015-06-11
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    相关资源
    最近更新 更多