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

学了点正则 还是不能匹配出聊天记录。

  •  
  •   jin6220 · 2018-07-20 17:16:56 +08:00 · 2586 次点击
    这是一个创建于 2316 天前的主题,其中的信息可能已经有所发展或是发生改变。
    想把群里特定用户的聊天记录导出来
    格式大概是这个样子
    ============================
    2016-09-13 18:39:56 苹果(1234567)
    这话说的,
    怎么样

    2016-09-13 20:40:04 香蕉(33445566)
    床前明月光,疑是地上霜。

    2016-09-13 21:40:26 土豆(180170160)
    我睡觉去,大家继续嗨

    2016-09-13 21:49:56 苹果(1234567)
    举头望明月,低头思故乡。

    2016-09-13 21:59:56 苹果(1234567)
    现在几点了就睡?

    2016-09-13 22:40:26 土豆(180170160)
    太困了。
    ===================
    比如想把苹果说过所有的话导出来,怎么个正则啊
    时间匹配用的是:
    \d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}
    自己写的表达式是:
    (\d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}\s{1,6}苹果\(1234567\)(\s.*)*(?=\d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}))
    运行结果是除了最后两行其他的都匹配了。
    想要的是结果是把所有苹果说的话弄出来。
    方法是匹配苹果的发言时间与下一个发言时间之间的内容,但是方法是错的。
    可以在这个网站测试
    https://regex101.com/
    第 1 条附言  ·  2018-07-20 22:50:26 +08:00
    总结一下,
    这是我之前写法:\d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}\s{1,6}苹果\(1234567\)(\s.*)*(?=\d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2})
    学习大家的代码我发现最主要差别的是匹配聊天记录的代码。
    我写的是(\s.*)*
    别人的是[\s\S]*?
    我那个写法中间改成(\s\S.*)*?或者(\s.*)*?为什么还不行呢。
    =========================================
    而只有中间换成[\s\S]*?即代码变成这样就可以了:
    \d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}\s{1,6}苹果\(1234567\)[\s\S]*?(?=\d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2})
    ===============================
    或者中间不变,加个?变成非贪婪模式变成这样(\s.*)*?,而后面断言的不要之前的,写成这样(?=[\d\-\s\:]{20})
    最后代码这样,也可以呢:
    \d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}\s{1,6}苹果\(1234567\)(\s.*)*?(?=[\d\-\s\:]{20})
    =======
    总之,解决了,以后再看看书吧
    第 2 条附言  ·  2018-07-20 23:18:19 +08:00
    对上面补充的再补充:
    是因为断言出错了,
    要么后面加个|$变成(?=\d{4}-\d{2}-\d{2}\s{1,6}\d{1,2}:\d{2}:\d{2}\s{1,6}|$)
    要么就用这个断言,(?=[\d\-\s\:]{20})
    24 条回复    2018-07-22 22:22:54 +08:00
    geelaw
        1
    geelaw  
       2018-07-20 17:20:07 +08:00
    太长不看,但我觉得你可以把

    (\s.*)*

    改成

    (\s.*)*?

    试试
    yesterdaysun
        2
    yesterdaysun  
       2018-07-20 17:23:53 +08:00   ❤️ 1
    硬上了一个,仅供参考
    \d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2} 苹果\(\d+\)[\r\n]+[\s\S]*?[\r\n]{2}
    jin6220
        3
    jin6220  
    OP
       2018-07-20 17:24:34 +08:00
    @geelaw 好的 谢谢 我试试
    jin6220
        4
    jin6220  
    OP
       2018-07-20 17:26:33 +08:00
    @yesterdaysun 哇 果然是大神 我废了半个小时吭哧吭哧 才编出了那个代码 看来还要提高水平。
    JCZ2MkKb5S8ZX9pq
        5
    JCZ2MkKb5S8ZX9pq  
       2018-07-20 17:30:59 +08:00
    一楼说得对 凑合用吧
    ^.*苹果\(1234567\)(\s.*)*?(?=[\d\-\s\:]{20})
    jin6220
        6
    jin6220  
    OP
       2018-07-20 17:32:00 +08:00
    @yesterdaysun 大神啊 这话说的后面的 怎么样没有匹配出来呐
    上面对话也是我编的,实际某个人发言格式可能很复杂 行与行之间还有空行。
    我的思路是比管你的发言内容是什么,我只匹配两个时间里面的内容。
    cncqw
        7
    cncqw  
       2018-07-20 17:32:04 +08:00   ❤️ 1
    太长不看

    20[\d-]{8}\s[\d:]{7,8}\s+[^\n]+(?:\d{5,11}|@\w+\.[comnet]{2,3})\)
    jin6220
        8
    jin6220  
    OP
       2018-07-20 17:34:48 +08:00
    @yesterdaysun 不好意思啊 刚才用的本地软件测试的,我用那个网站测试了。实际结果是匹配出来的,我要好好研究下你的代码。
    zihuyishi
        9
    zihuyishi  
       2018-07-20 17:43:13 +08:00
    感觉这里没必要用正则额....
    ETiV
        10
    ETiV  
       2018-07-20 17:44:44 +08:00
    这样?
    苹果\(\d+\)\s+(^.*$\n)+?^$

    jin6220
        11
    jin6220  
    OP
       2018-07-20 17:52:08 +08:00
    @ETiV 包括前面的时间,这样呢,红框那些发言,
    http://p3.cdn.img9.top/ipfs/QmebK5JAqyGBJsZNNaCa4svtBirfeSxhbcVrenStL8yVVR?3.jpg
    ETiV
        12
    ETiV  
       2018-07-20 18:01:22 +08:00
    包括时间那么简单你自己写啦(或者用 2 楼的,「苹果」之前那一串)
    FanWall
        13
    FanWall  
       2018-07-20 18:03:49 +08:00 via Android
    ```
    20\d{2}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2} 苹果\([^\)]+\) \n(((?!20\d{2}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2} ).)+)
    ```

    考虑一下不以两个\n 结束以及 QQ 号未必是纯数字的对话,选择单行模式,/gs
    LudwigWS
        14
    LudwigWS  
       2018-07-20 18:04:46 +08:00
    问题是如何导出聊天记录。。
    jin6220
        15
    jin6220  
    OP
       2018-07-20 18:07:44 +08:00
    @LudwigWS 喇叭状的按钮,打了消息管理器,导出即可。我选择的 txt 格式。
    future0906
        16
    future0906  
       2018-07-20 19:18:21 +08:00
    其实你做的这些都是徒劳的,如果人在说话的过程中贴了聊天记录,你怎么提取?
    gam2046
        17
    gam2046  
       2018-07-20 20:52:09 +08:00
    (?<=苹果.+\n)[\s\S]*?(?=\d{4}-\d{2}-\d{2}|$)

    要不要试试看?但依旧觉得,这个不应该用正则来做,最多正则选取出来每个人说的话,然后用程序根据每个人说的话,再做二次筛选会灵活很多
    jin6220
        18
    jin6220  
    OP
       2018-07-20 20:59:18 +08:00
    @future0906 哈哈 确实 只能匹配大概正确的 。
    如果别人把含有他的多个聊天记录贴上来,只能把苹果每次发言的最后一个时间记录下来,如果下次他的发言时间大于上述时间,再用正则匹配。
    jin6220
        19
    jin6220  
    OP
       2018-07-20 21:09:37 +08:00
    @gam2046 我也不太懂啊 就是把群聊天消息导出到 txt 格式 到时候用过正则弄出特定用户的发言,您觉得是怎么做好呢。另外,你这个正则 好像不能匹配苹果发言。
    gam2046
        20
    gam2046  
       2018-07-20 21:13:27 +08:00
    @jin6220 可变长度断言,JavaScript 并不支持而已。这个特性看正则引擎的。不要断言就直接改用捕获分组咯,不过是速度会略慢一点,不过你这个用途也无所谓,根本看不出来。

    (苹果.+\n)([\s\S]*?)(\d{4}-\d{2}-\d{2}|$)

    第二个分组的内容,就是你要的东西。
    frostming
        21
    frostming  
       2018-07-20 22:19:47 +08:00
    把(\s.*)*换成:' *\n([\s\S]*?)'
    jin6220
        22
    jin6220  
    OP
       2018-07-20 23:19:19 +08:00
    @frostming 嗯 为什么写成这样不行呢 (\s\S.*)*?
    zhzer
        23
    zhzer  
       2018-07-22 21:48:03 +08:00
    这种情况,就分步骤正则嘛
    简单的逻辑加上正则,比精心编排的正则省时省力
    frostming
        24
    frostming  
       2018-07-22 22:22:54 +08:00
    @jin6220 (\s\S.*)*?的意思是匹配:([一个空格][一个非空格][任意长度字符])重复任意次,中括号之间是顺序匹配关系。这就只能匹配 " xxxx yyyy zzzz dddd..."这种字符串了呀
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   972 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 20:53 · PVG 04:53 · LAX 12:53 · JFK 15:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.