【问题标题】:Parsing URI parameter and keyword value pairs解析 URI 参数和关键字值对
【发布时间】:2013-09-14 14:08:21
【问题描述】:

我想从文本文件中的 URI/L 解析参数和关键字值。没有值的参数也应该包括在内。 Python 很好,但我愿意接受使用其他工具的建议,例如 Perl 或也可以做到这一点的单线器。

示例来源:

www.domain.com/folder/page.php?date=2012-11-20
www2.domain.edu/folder/folder/page.php?l=user&x=0&id=1&page=http%3A//domain.com/page.html&unique=123456&refer=http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname&text=
www.domain.edu/some/folder/image.php?l=adm&y=5&id=2&page=http%3A//support.domain.com/downloads/index.asp&unique=12345
blog.news.org/news/calendar.php?view=month&date=2011-12-10

示例输出:

date=2012-11-20
l=user
x=0
page=http%3A//domain.com/page.html&unique=123456
refer=http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname
test=
l=adm
y=5
id=2
page=http%3A//support.domain.com/downloads/index.asp
unique=12345
view=month
date=2011-12-10

【问题讨论】:

    标签: python parsing url


    【解决方案1】:

    您无需深入了解脆弱的正则表达式世界。

    urlparse.parse_qsl() 是工作的工具(urllib.quote() 有助于转义特殊字符):

    from urllib import quote
    from urlparse import parse_qsl, urlparse
    
    
    with open('links.txt') as f:
        for url in f:
            params = parse_qsl(urlparse(url.strip()).query, keep_blank_values=True)
            for key, value in params:
                print "%s=%s" % (key, quote(value))
    

    打印:

    date=2012-11-20
    l=user
    x=0
    id=1
    page=http%3A//domain.com/page.html
    unique=123456
    refer=http%3A//domain2.net/results.aspx%3Fq%3Dbob%20test%201.21%20some%26file%3Dname
    text=
    l=adm
    y=5
    id=2
    page=http%3A//support.domain.com/downloads/index.asp
    unique=12345
    view=month
    date=2011-12-10
    

    希望对您有所帮助。

    【讨论】:

    • 如果你改用parse_qsl,你会得到一个列表而不是字典。
    • @KirkStrauser 谢谢,parse_qsl 的代码看起来更好。
    【解决方案2】:

    我会使用这样的正则表达式(第一个代码然后解释):

    pairs = re.findall(r'(\w+)=(.*?)(?:\n|&)', s, re.S)
    for k, v in pairs:
        print('{0} = {1}'.format(k, v))
    

    第一行是动作发生的地方。正则表达式查找所有出现的单词,后跟等号,然后是一个以& 或换行符结尾的字符串。返回pairs 是一个元组列表,其中每个元组包含单词(关键字)和值。我没有捕获= 符号,而是在循环中打印它。

    解释正则表达式:

    \w+ 表示一个或多个单词字符。它周围的括号表示捕获它并返回该值作为结果。

    = - 必须跟在单词后面的等号

    .*? - 零个或多个字符以非贪婪方式,直到出现新行或& 符号,由\n|& 指定。 (?:.. 模式意味着不应捕获 \n&

    由于我们在正则表达式中捕获了 2 个内容 - 关键字和 = 符号之后的所有内容,因此会返回一个 2 元组列表。

    re.S 告诉正则表达式引擎允许匹配所有正则表达式代码 - . - 在搜索中也包括新行字符,即允许搜索跨越多行(这不是默认值行为)。

    【讨论】:

    • 对于像这样的几乎所有通用函数,您可以假设它已经在标准库中定义。在这种情况下,请在“urlparse”中查找一些不涉及编写自己的正则表达式的替代方案。
    • 同意。郑重声明:不是我。
    • 抱歉,删除了我的评论
    【解决方案3】:

    您可以使用正则表达式来提取所有对。

    >>> url = 'www2.domain.edu/folder/folder/page.php?l=user&x=0&id=1&page=http%3A//domain.com/page.html&unique=123456&refer=http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname&text='
    >>> import re
    >>> url = 'www2.domain.edu/folder/folder/page.php?l=user&x=0&id=1&page=http%3A//domain.com/page.html&unique=123456&refer=http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname&text='
    >>> p = re.compile('.*?&(.*?)=(.*?)(?=&|$)')
    >>> m = p.findall(url)
    >>> m
    [('x', '0'), ('id', '1'), ('page', 'http%3A//domain.com/page.html'), ('unique', '123456'), ('refer', 'http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname'), ('text', '')]
    

    您甚至可以使用字典推导将所有数据打包在一起。

    >>> dic = {k:v for k,v in m}
    >>> dic
    {'text': '', 'page': 'http%3A//domain.com/page.html', 'x': '0', 'unique': '123456', 'id': '1', 'refer': 'http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname'}
    

    然后,如果您只想将它​​们打印出来:

    >>> for k,v in dic.iteritems():
        print k,'-->',v
    
    text --> 
    page --> http%3A//domain.com/page.html
    x --> 0
    unique --> 123456
    id --> 1
    refer --> http%3A//domain2.net/results.aspx%3Fq%3Dbob+test+1.21+some%26file%3Dname
    

    【讨论】:

    • 这不会取消引用任何值。但更重要的是,urlparse.parse_qs 会为您完成所有这些工作。
    • 另一种解决方案,可以更轻松地工作和移植到其他语言,但不使用神奇的 url 库...DOWNVOTE!
    • 我投了反对票,因为在您希望输出值与最初输入时相同的一般情况下,它实际上不能正常工作。您的解决方案会忽略一个转义-非转义循环,因此对于大多数用例,输出将被视为不正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多