如何过滤包含 Python 中的子字符串的 jsonpath 表达式中的 URL 列表

Posted

技术标签:

【中文标题】如何过滤包含 Python 中的子字符串的 jsonpath 表达式中的 URL 列表【英文标题】:How to filter list of URLs in a jsonpath expression containing a substring in Python 【发布时间】:2014-02-27 11:20:17 【问题描述】:

我必须过滤包含 Python 中的子字符串的 jsonpath 表达式中的 URL 列表,我尝试了以下但无法获得所需的结果。

我提到了http://goessner.net/articles/JsonPath/和http://mikelev.in/2012/08/implementing-jsonpath-in-python-with-examples/

以下是我尝试过的所有方法的详细信息:

我的 json 响应:


  "127.0.0.1": 
    "URLs": [
      "http://www.test.ca/", 
      "http://b.scorecardresearch.com/p?ns__t=1387392184071&ns__c=ISO-8859-1&c1=3&c3=_es_7948950&c4=56568219&c5=105139691&c6=&c10=1&c11=1016510&c13=728x90&c16=dfa&c2=14397547&ax_iframe=2&ns_ce_mod=vce_st&ns__p=1387391507295&ax_cid=14397547&ax_bl=0&ax_blt=1228&ns_ad_event=show&ns_ad_id=DCF277937840&ns_ad_sz=728x90", 
      "http://cdn.media.ca/a/mediative/sites/test_en.js", 
      "http://pt200233.unica.com/ntpage.gif?js=1&ts=1387392184554.791&lc=http%3A%2F%2Fwww.test.ca%2F%3Fni_title%3D%2Fhome%2Fhomepage&rf=http%3A%2F%2Fwww.test.ca%2F&rs=1680x1050&cd=32&ln=en&tz=GMT%20-05%3A00&jv=1&ck=UnicaID%3DwQVZatfvXZ5-YZ0yaPj&m.pn=homepage&m.mlc=%2Fhome&m.cv_c13=ctest-new&m.cv_c14=en&m.utv=ut.ctest.2.2.131022.74&m.host=www.test.ca&m.page=%2Fhome%2Fhomepage&m.mlc0=home&ets=1387392184559.194&site=test", 
    ]
  

上面的Json响应被解析为:

parsed_input = json.loads(urllib.urlopen('<URL for the above JSON response>').read())

为了从 JSON 响应中获取所有 URL 的列表,我尝试了以下方法,效果很好:

'\n'.join(jsonpath.jsonpath(parsed_input, '$..URLs[*]'))

输出:

http://www.test.ca/
http://b.scorecardresearch.com/p?ns__t=1387392184071&ns__c=ISO-8859-1&c1=3&c3=_es_7948950&c4=56568219&c5=105139691&c6=&c10=1&c11=1016510&c13=728x90&c16=dfa&c2=14397547&ax_iframe=2&ns_ce_mod=vce_st&ns__p=1387391507295&ax_cid=14397547&ax_bl=0&ax_blt=1228&ns_ad_event=show&ns_ad_id=DCF277937840&ns_ad_sz=728x90"    
http://cdn.media.ca/a/mediative/sites/test_en.js"    
http://pt200233.unica.com/ntpage.gif?js=1&ts=1387392184554.791&lc=http%3A%2F%2Fwww.test.ca%2F%3Fni_title%3D%2Fhome%2Fhomepage&rf=http%3A%2F%2Fwww.test.ca%2F&rs=1680x1050&cd=32&ln=en&tz=GMT%20-05%3A00&jv=1&ck=UnicaID%3DwQVZatfvXZ5-YZ0yaPj&m.pn=homepage&m.mlc=%2Fhome&m.cv_c13=ctest-new&m.cv_c14=en&m.host=www.test.ca&m.page=%2Fhome%2Fhomepage&m.mlc0=home&ets=1387392184559.194&site=test

接下来,我将只检索那些包含“unica”一词的 URL。 我已尝试以下所有方法,但收到 TypeError, 我错过了什么?:

'\n'.join(jsonpath.jsonpath(parsed_input, '$..URLs[?(/unica/)]'))
'\n'.join(jsonpath.jsonpath(parsed_input, '$..URLs[?(@(unica))]'))
'\n'.join(jsonpath.jsonpath(parsed_input, '$..URLs[?(@.(*.unica.*))]'))
'\n'.join(jsonpath.jsonpath(parsed_input, '$.*.URLs[?(unica)]'))
'\n'.join(jsonpath.jsonpath(parsed_input, '$.*.URLs[?:unica]'))

谢谢, 山姆

【问题讨论】:

[x for x in '\n'.join(jsonpath.jsonpath(parsed_input, '$..URLs[*]')) if 'unica' in x] 嘿 Nehal,它打印 [],这里有什么遗漏吗? 【参考方案1】:

那个?运算符引入了一个在 Python 中运行的脚本元素,因此需要使用 Python 语法。

在这种情况下,您可以使用:

print '\n'.join(jsonpath.jsonpath(parsed_input, "$..URLs[?('unica' in @)]"))

对这些情况有用的选项是通过以下方式使用调试选项:

jsonpath.jsonpath(parsed_input, '$..URLs[?(/unica/)]',debug=True)

这会打印出各种输出,包括:

evalx /unica/
eval /unica/
invalid syntax (<string>, line 1)

“eval /unica/”行向您展示了 Python 中正在运行的内容,以便您查看失败的内容。

【讨论】:

感谢 Peter 分享解决方案以及使用调试选项的建议!它有效! 这里是 javascriptjsonPath(parsed_input, "$..URLs[?( /unica/.test(@) )]")【参考方案2】:

按照 Peter 的解释,如果需要,您实际上可以在 jsonpath 过滤表达式中使用正则表达式,使用内置的 dunder import。

jsonpath.jsonpath(parsed_input, "$..URLs[?(__import__('re').match('.*unic', @))]") 

进一步看,jsonpath 是 hack 的集合,特别是有这样一行:

# Get caller globals so eval can pick up user functions!!!
caller_globals = sys._getframe(1).f_globals

因此,如果在您调用jsonpath.jsonpath 的模块中导入了re,这也是:

jsonpath.jsonpath(parsed_input, "$..URLs[?(re.match('.*unic', @))]") 

【讨论】:

以上是关于如何过滤包含 Python 中的子字符串的 jsonpath 表达式中的 URL 列表的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AWS Redshift 数据库中获取过滤器和分组依据子句的子字符串

如何使用包含子字符串的字段过滤文档

Python Dataframe:DF列中的字符串包含来自不同DF的子字符串和匹配时返回的子字符串值

修改 Python 类以过滤文件

如何匹配 MongoDB 中的子文档数组?

如何检查一个对象是不是至少包含一个键,其值包含 JavaScript 中的子字符串?