V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
jin6220
V2EX  ›  Python

想了一个多小时,求个{正则}大神看看如何正则出下面 json 里的数据。

  •  
  •   jin6220 · 2017-01-14 23:02:10 +08:00 · 3905 次点击
    这是一个创建于 2868 天前的主题,其中的信息可能已经有所发展或是发生改变。
    每次正则都有从头看一遍,
    想了一个多小时了。
    就把标题给正则出了
    还有标题下下面的网址求问如何弄出来?
    "title_hide": "给你的键盘加上无线 PPT 控制功能吧",
    "date_modified": "2013-05-24T11:23:42.260648+08:00",
    "url": "http://www.guokr.com/article/437046/",
    "title": "给你的键盘加上无线 PPT 控制功能吧",
    "small_image": "http://2.im.guokr.com/BFnIhI2uKOFbTt44KurAN3zMyaJjXmao9OciN4ayjkLgAQAASQEAAEpQ.jpg",
    "summary": "这个项目也是一个很好的焊接技巧入门练习。",
    "ukey_author": "m4tq2j",
    "date_created": "2013-05-24T11:19:42.252645+08:00",
    "resource_url": "http://apis.guokr.com/minisite/article/437046.json"
    上面代码是 json 一角,需要的部分是 title_hide ,这个已解出,另一个部分是下下行的 url.


    这是我写的代码:

    import requests
    import re
    import json
    from bs4 import BeautifulSoup
    headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'}
    def gker(url):
    html=requests.get(url, headers=headers).text
    return html

    j=gker('http://www.guokr.com/apis/minisite/article.jsonretrieve_type=by_subject&subject_key=diy&limit=20&offset=18&_=1484373021355')
    j2=str(json.loads(j)) #必须转换成字符串才能正则匹配。

    titles=re.findall(r"(?<='title_hide':).*?(?=,)",j2,re.M)
    print(len(titles))
    for title in titles:
    print(title)

    urls=re.findall(r"'url':(.*?),.?'title'",j2,re.M) #这里不对,不知道如何弄出来了
    print(len(urls),urls)
    38 条回复    2017-01-16 08:55:39 +08:00
    jin6220
        1
    jin6220  
    OP
       2017-01-14 23:07:37 +08:00
    for title in titles:
    print(title)
    别人上传的代码怎么那么结构清晰啊 =,=
    zhjits
        2
    zhjits  
       2017-01-14 23:09:20 +08:00
    直接读 JSON 转成的 dict 不行么
    decken
        3
    decken  
       2017-01-14 23:11:52 +08:00 via iPhone
    用 json.loads 反序列化出对象,再 get 一下就 ok 了
    golmic
        4
    golmic  
       2017-01-14 23:12:00 +08:00 via Android
    url":"[^"]+
    privil
        5
    privil  
       2017-01-14 23:12:02 +08:00 via iPhone
    @jin6220 别人用 md 格式了呗,楼上正解, json 搞出来的事 dict ,打印字典指定值被
    cdwyd
        6
    cdwyd  
       2017-01-14 23:12:13 +08:00 via Android
    re.compile('article/(\d+)/')
    fy
        7
    fy  
       2017-01-14 23:13:38 +08:00
    这需求不要用正则,本身例外多早晚出事。直接 json 解轻松愉快。
    jin6220
        8
    jin6220  
    OP
       2017-01-14 23:13:55 +08:00
    @zhjits 是已经转换成 dict 了 但是现在正则已经弄出一半数据了 。。。
    Yinz
        9
    Yinz  
       2017-01-14 23:18:44 +08:00
    如果不要求一定用正则的话, json 直接读成 dict 就好了,如 3 、 5 楼所说

    j2=str(json.loads(j)) #必须转换成字符串才能正则匹配。

    titles=re.findall(r"(?<='title_hide':).*?(?=,)",j2,re.M)
    print(len(titles))
    for title in titles:
    print(title)

    urls=re.findall(r"'url':(.*?),.?'title'",j2,re.M) #这里不对,不知道如何弄出来了
    print(len(urls),urls)

    上面这几行改成
    j2=json.loads(j)
    print(j2.get('title_hide'))
    print(j2.get('url'))

    应该就没问题的了
    Yinz
        10
    Yinz  
       2017-01-14 23:19:28 +08:00
    @jin6220 沉没成本不要算啊,毕竟转 dict 之后简单太多了
    jin6220
        11
    jin6220  
    OP
       2017-01-14 23:21:12 +08:00
    当初没用字典是嫌麻烦,各种套嵌。看来明天还得再看看正则。
    jin6220
        12
    jin6220  
    OP
       2017-01-14 23:23:50 +08:00
    ======自答下:=========
    第一步: a=j2['result'] (这里 j2 就不用字符串话了)
    第二部:
    >>> for b in a :
    print(b.get('title_hide'))


    制作一个万花筒,来一场镜花水月的邂逅
    让翅膀在指尖上舞动:用铁丝制作在指尖扇动的小机械
    来做一个漂亮的鱼标本吧!
    低成本打造头戴式立体声蓝牙耳机
    自动温调速风扇,让你的电脑更冷静
    给你的键盘加上无线 PPT 控制功能吧
    给钛挂件镀一层彩色外衣
    泥塑入门,做个蒸汽朋克范儿黄金头骨
    送妹纸魔方拼图,你也可以
    温差发电机:不用电的“智能”风扇
    手机?投影机?一个盒子就可兼得!
    GEEK 小浪漫:靠在一起就会闪烁的心
    制作属于你自己的球形关节人偶
    GEEK 厨房之草莓酱,和一坨肉眼可见 DNA
    沏一壶苔藓
    软木塞变身灰袍甘道夫
    自制模具,巧克力形状随便你
    情人节,送 Ta 一支彩虹玫瑰!
    远程电子点火器,安全烟火必备
    化学小实验:居家版“法老之蛇”
    >>> for b in a :
    print(b.get('url'))


    http://www.guokr.com/article/437636/
    http://www.guokr.com/article/437297/
    http://www.guokr.com/article/437489/
    http://www.guokr.com/article/437145/
    http://www.guokr.com/article/437064/
    http://www.guokr.com/article/437046/
    http://www.guokr.com/article/437010/
    http://www.guokr.com/article/436762/
    http://www.guokr.com/article/436941/
    http://www.guokr.com/article/436937/
    http://www.guokr.com/article/436912/
    http://www.guokr.com/article/436915/
    http://www.guokr.com/article/436835/
    http://www.guokr.com/article/436799/
    http://www.guokr.com/article/436722/
    http://www.guokr.com/article/436694/
    http://www.guokr.com/article/436679/
    http://www.guokr.com/article/436667/
    http://www.guokr.com/article/436640/
    http://www.guokr.com/article/436644/
    >>>
    jin6220
        13
    jin6220  
    OP
       2017-01-14 23:28:59 +08:00
    @Yinz 嗯 你那个结构好像不对 但是换成 json 无非就是套嵌 dict 循环下就立马解出了 正则不如派森像是人类语言啊啊啊
    但是还是很想弄懂正则怎么写 毕竟有时候只有正则解决问题很暴力 =,=
    lxy
        14
    lxy  
       2017-01-15 00:25:13 +08:00
    要是有人在工作中有 json 不用非要用正则写一堆“乱码”会被我捏脸的。 4 楼那个就是了,不过漏了空格,稍微严谨一点的写法:
    "url"\s*:\s*"(.+?)"\s*,
    Allianzcortex
        15
    Allianzcortex  
       2017-01-15 00:42:13 +08:00
    其实我想说的很多时候返回的 JSON 格式顺序是不固定的,调好了这一个正则,下次请求的时候内容就又变了。所以???
    Yinz
        16
    Yinz  
       2017-01-15 00:42:20 +08:00
    @jin6220 这。。。别循环啊,自己分析下 json 的格式然后逐步 get 就好了,没必要循环找元素吧
    jin6220
        17
    jin6220  
    OP
       2017-01-15 07:47:28 +08:00
    @Yinz 里头的主体结构类似是:
    { "result": [{"title_hide": ...,,"url": ...},{title_hide:...,url:...},{title_hide:...,url:...},,{title_hide:...,url:...},其他字典]}
    result 的值是一个列表,列表里的字典都是并列结构,不循环可以?
    jin6220
        18
    jin6220  
    OP
       2017-01-15 08:37:50 +08:00
    wyntergreg
        19
    wyntergreg  
       2017-01-15 08:57:55 +08:00
    不用 JSON 非要正则,舍近求远?
    allenhu
        20
    allenhu  
       2017-01-15 09:12:48 +08:00 via Android
    无知者无畏
    jin6220
        21
    jin6220  
    OP
       2017-01-15 09:21:32 +08:00
    @allenhu 我是新手,不过也不从事程序猿专业,接触的数据应该都会很简单。
    jin6220
        22
    jin6220  
    OP
       2017-01-15 09:40:06 +08:00
    正则前后关系匹配:"url"\s*:\s*"(.+?)"\,\s*"title re.M
    但是实际 url 的邻居可能会变.
    jin6220
        23
    jin6220  
    OP
       2017-01-15 09:46:28 +08:00
    吃饭去了。。。
    总结下
    非正则的办法:
    第一步: a=j2['result'] (这里 j2 就不用字符串话了)
    a 是一个列表,里面是 20 个并联关系的字典。
    第二部:
    >>> for b in a :
    print(b.get('title_hide'))
    >>> for b in a :
    print(b.get('url'))

    正则方法:
    第一种
    urls=re.findall(r"(?<='url':)\s*'http://www.guokr.com/article/\d{5,7}/'(?=,)",str(j2))
    第二种(看运气,前后邻居可能会变,然后就失效)
    urlsre=re.findall(r"'url'\s*:\s*'(.+?)',\s*'title'",str(j2),re.M)
    Valyrian
        24
    Valyrian  
       2017-01-15 09:56:11 +08:00 via iPad   ❤️ 1
    这是理论上行不通的,因为 regex parse 的是 regular language , json isn't a regular language
    http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags
    aheadlead
        25
    aheadlead  
       2017-01-15 10:05:40 +08:00 via iPad
    @lxy 捏脸好评
    jin6220
        26
    jin6220  
    OP
       2017-01-15 10:22:22 +08:00
    @Valyrian 理论是不行,第一次也是发现不对,然后就把 json ( dict )数据 str 化了,最后是找到结果了。
    sola97
        27
    sola97  
       2017-01-15 10:31:31 +08:00 via Android
    这么简单还不用 dict...有写正则的功夫早就 get 完了
    Merlini
        28
    Merlini  
       2017-01-15 11:09:14 +08:00 via Android
    而且正则也慢啊
    zzn
        29
    zzn  
       2017-01-15 11:56:46 +08:00   ❤️ 1
    解析 xml/json 不要用正则
    解析 xml/json 不要用正则
    解析 xml/json 不要用正则
    zhidian
        30
    zhidian  
       2017-01-15 12:00:07 +08:00
    JSON 也有 xpath 类似的工具啊……
    jin6220
        31
    jin6220  
    OP
       2017-01-15 12:04:03 +08:00
    @zzn 那用什么啊 对这块不太懂 这个 json 没显示汉字,变成字典显示之后然后正则的
    imlonghao
        32
    imlonghao  
       2017-01-15 12:34:34 +08:00
    import requests

    a = requests.get('http://www.guokr.com/apis/minisite/article.json?retrieve_type=by_subject&subject_key=diy&limit=20&offset=18&_=1484373021355').json()

    result = [[x['title_hide'], x['url']] for x in a['result']]
    imlonghao
        33
    imlonghao  
       2017-01-15 12:35:48 +08:00
    不!要!用!正!则!处!理 json 数!据!
    jin6220
        34
    jin6220  
    OP
       2017-01-15 13:20:15 +08:00
    @imlonghao 嗯 这个列表表达式用的好 学习了 比 for 循环简洁,但是没 for 循环好理解。
    eoo
        35
    eoo  
       2017-01-15 23:14:55 +08:00 via Android
    PHP json_decode($json); 搞定 啊哈哈
    Ouyangan
        36
    Ouyangan  
       2017-01-16 00:09:52 +08:00
    正则处理 json 属于野路子.本身就是结构化的数据为什么用正则呢?
    xiamx
        37
    xiamx  
       2017-01-16 01:35:48 +08:00
    @jin6220 楼主看看 @Valyrian 给的链接。 JSON 是 Context-free grammar ,不是 regular language 所以不能用正则解析(当然,某些子集还是属于 regular language 的)
    jin6220
        38
    jin6220  
    OP
       2017-01-16 08:55:39 +08:00
    @xiamx 好吧 谢谢,有个疑问,那个网站的 json 数据转换为字典之后(因为里头的汉字没显示出来。),然后 str 字符串化,这样正则可以吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3498 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 04:29 · PVG 12:29 · LAX 20:29 · JFK 23:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.