【问题标题】:Python parsingPython解析
【发布时间】:2010-10-11 02:26:24
【问题描述】:

我正在尝试将 RSS 2.0 提要中的标题标签解析为该提要中每个条目的三个不同变量。使用 ElementTree,我已经解析了 RSS,以便我可以使用以下代码打印每个标题 [减去结尾的 )]:

feed = getfeed("http://www.tourfilter.com/dallas/rss/by_concert_date")

for item in feed:  
 print repr(item.title[0:-1])

我包含它是因为,如您所见,item.title 是一种 repr() 数据类型,我对此不太了解。

交互窗口中特定的repr(item.title[0:-1])printed 如下所示:

'randy travis (Billy Bobs 3/21'
'Michael Schenker Group (House of Blues Dallas 3/26'

用户选择了一个乐队,我希望在将每个 item.title 解析为 3 个变量(乐队、场地和日期各一个......或者可能是一个数组或者我不知道......)选择只有那些与所选乐队相关的人。然后将它们发送到 Google 进行地理编码,但这是另一回事。

我看过一些regex 的例子,我正在阅读它们,但它似乎非常复杂。是吗?我想也许这里有人会对如何以一种智能的方式做到这一点有一些见解。我应该使用re 模块吗?输出当前是repr()s 是否重要?有没有更好的办法?我在想我会使用像这样的循环(这是我的伪 Python,只是我正在写的一种笔记):

列表 = bandRaw、地点、日期、latLong 对于提要中的项目: 为 bandRaw、地点、日期解析 item.title 如果 bandRaw == str(band) 将场地名称+“,达拉斯,德克萨斯”发送到谷歌进行地理编码 返回纬度,经度 list = list + return character + bandRaw + "," + place + "," + date + "," + lat + "," + long 别的

最后,我需要在 .csv(逗号分隔)文件中选择如下所示的条目:

band,venue,date,lat,long  
randy travis,Billy Bobs,3/21,1234.5678,1234.5678  
Michael Schenker Group,House of Blues Dallas,3/26,4321.8765,4321.8765

我希望这不是太多要求。我会自己研究它,只是想我应该在这里发帖以确保它得到回答。

那么,问题是,我如何最好地将feed 中的每个repr(item.title[0:-1]) 解析为3 个单独的值,然后我可以将它们连接成一个.csv 文件?

【问题讨论】:

    标签: python regex parsing text-parsing


    【解决方案1】:

    不要让正则表达式吓跑你……它非常值得学习。

    鉴于上述示例,您可以尝试将尾括号放回原处,然后使用以下模式:

    import re
    pat = re.compile('([\w\s]+)\(([\w\s]+)(\d+/\d+)\)')
    info = pat.match(s)
    print info.groups()
    
    ('Michael Schenker Group ', 'House of Blues Dallas ', '3/26')
    

    要了解每个组的个人,只需在 info 对象上调用他们:

    print info.group(1) # or info.groups()[0]
    
    print '"%s","%s","%s"' % (info.group(1), info.group(2), info.group(3))
    "Michael Schenker Group","House of Blues Dallas","3/26"
    

    在这种情况下,正则表达式的难点在于确保您知道标题中所有已知的可能字符。如果“Michael Schenker Group”部分中有非 alpha 字符,则必须调整该部分的正则表达式以允许它们。

    上面的模式分解如下,从左到右解析:

    ([\w\s]+):匹配任何单词或空格字符(加号表示应该有一个或多个这样的字符)。括号表示匹配将作为一个组被捕获。这是“Michael Schenker Group”的一部分。如果此处可以有数字和破折号,您需要修改方括号之间的部分,这是该集合的可能字符。

    \( :文字括号。反斜杠转义括号,否则它被视为正则表达式命令。这是字符串的“(”部分。

    ([\w\s]+) : 同上一个,但这次匹配的是“达拉斯蓝调之家”部分。在括号中,因此它们将被捕获为第二组。

    (\d+/\d+) :匹配数字 3 和 26,中间有一个斜线。在括号中,因此它们将被捕获为第三组。

    \):上面的右括号。

    正则表达式的 Python 介绍非常好,您可能想花一个晚上的时间来阅读它http://docs.python.org/library/re.html#module-re。另外,请查看 Dive Into Python,其中有友好的介绍:http://diveintopython3.ep.io/regular-expressions.html

    编辑:请参阅下面的 zacherates,他有一些不错的编辑。两个头比一个好!

    【讨论】:

    • 感谢您的回答!这很有帮助!不过我有点困惑......我需要单独识别字段以发送给谷歌并连接。我如何调用每个值?例如,我将如何连接这些值?
    • 您的正则表达式在乐队和场地名称上留下了尾随空格,但这很容易解决。
    • 是的,我也注意到了,但我想我会在每个 item.title 的前两个值上使用 [0:-1] 技巧。
    • 而他对 (.*) 的搜索解决了字符问题,只要你不将正则表达式设置为贪婪
    • 我在帖子中编辑了一些关于连接的信息...希望我能正确理解您的意图。
    【解决方案2】:

    正则表达式是解决这个问题的好方法:

    >>> import re
    >>> s  = 'Michael Schenker Group (House of Blues Dallas 3/26'
    >>> re.match(r'(.*) \((.*) (\d+/\d+)', s).groups()
    ('Michael Schenker Group', 'House of Blues Dallas', '3/26')
    

    作为旁注,您可能需要查看 Universal Feed Parser 以处理 RSS 解析,因为提要有格式错误的坏习惯。

    编辑

    关于您的评论...字符串偶尔被包裹在 "s 而不是 's 与您使用 repr 的事实有关。字符串的 repr 通常用 's 分隔,除非那字符串包含一个或多个 's,而它使用 "s 以便不必对 's 进行转义:

    >>> "Hello there"
    'Hello there'
    >>> "it's not its"
    "it's not its"
    

    注意不同的引用风格。

    【讨论】:

    • 感谢您的回答!至于您的旁注,我注意到有些条目的开头和结尾都带有“”而不是“”。我想知道这是否会成为问题。我使用了effbot.org/zone/element-rss-wrapper.htm 提供的 RSS 解析器。
    【解决方案3】:

    关于repr(item.title[0:-1]) 部分,不确定你从哪里得到的,但我很确定你可以简单地使用item.title。您所做的只是从字符串中删除最后一个字符,然后在其上调用 repr(),这无济于事。

    您的代码应如下所示:

    import geocoders # from GeoPy
    us = geocoders.GeocoderDotUS()
    
    import feedparser # from www.feedparser.org
    feedurl = "http://www.tourfilter.com/dallas/rss/by_concert_date"
    feed = feedparser.parse(feedurl)
    
    lines = []
    for entry in feed.entries:
        m = re.search(r'(.*) \((.*) (\d+/\d+)\)', entry.title)  
        if m:
            bandRaw, venue, date = m.groups()
    
            if band == bandRaw:
                place, (lat, lng) = us.geocode(venue + ", Dallas, TX")
                lines.append(",".join([band, venue, date, lat, lng]))
    
    result = "\n".join(lines)
    

    EDIT:将list 替换为lines 作为var 名称。 list 是内置的,不应用作变量名。对不起。

    【讨论】:

    • :::sigh::: 看起来你用比我导入的更少的行写了整个东西......你使用什么模块?特别是对于 get_geo 和 list.append? list 是一个内置,对吗?获取地理?是来自 GeoPy 的吗?
    • 最后一行添加换行符?这也很有帮助。感谢您抽出宝贵时间。
    • 很抱歉,如果不清楚,但我编造了 get_geo。我只是将它用作您决定实现的任何功能的占位符。
    猜你喜欢
    • 2016-07-26
    • 2015-05-04
    • 2013-08-14
    • 2012-11-25
    • 2012-01-26
    • 2012-01-03
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多