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
blackantt
V2EX  ›  Python

.*?的缺陷谁能说说? 在一个超大字符串(没分行数据)里用 5 个左右的 .*? 会出现不可预料的结果

  •  
  •   blackantt · 2022-10-10 13:48:16 +08:00 · 2502 次点击
    这是一个创建于 767 天前的主题,其中的信息可能已经有所发展或是发生改变。

    .?的缺陷谁能说说? 在一个超大字符串(没分行数据)里用 5 个左右的 .? 会出现不可预料的结果

    按记录分行后,.? 就正常了。 问题是就算对记录预先分行,如果每次都先按记录来分行,再 .? 。 那工作量太大。 如果分错, 那结果也就不对了。

    详见, https://fishc.com.cn/thread-219007-1-1.html

    第 1 条附言  ·  2022-10-10 17:26:18 +08:00
    需求,代码,以及 bug 说明都在包里。 不用密码,直接点击下载,https://www.alpacadisk.com/shared/DFnmIuBtzbrgR8hL


    请解释下 .*? 的 bug 问题。 以及类似问题用.*?怎么弄? 如果不用.*?哪又怎么弄?
    第 2 条附言  ·  2022-10-10 20:55:17 +08:00
    刚才知道,正则不适合搞 html. 以前还真不知道
    8 条回复    2022-10-14 14:59:43 +08:00
    wxf666
        1
    wxf666  
       2022-10-10 14:14:03 +08:00   ❤️ 2
    怎么下载样例文件呢。。还要注册个账号?会不会积分不够,还得灌个水啥的?

    除非搜索 /替换需求特别简单,否则正则不适合用于 html xml 这种数据上

    推荐 BeautifulSoup lxml 等库,使用里面的 css selector 或 xpath 功能
    fbichijing
        2
    fbichijing  
       2022-10-10 16:21:46 +08:00
    @wxf666 确实如此。一开始的时候我还喜欢用正则去抓取某些不是很规则的数据,感觉还有那么一丢丢的方便。但随着使用次数的增多,发现直接使用提取器更加简单直接,节省去测试正则的时间。
    blackantt
        3
    blackantt  
    OP
       2022-10-10 17:28:09 +08:00
    @wxf666 重新上传到一个直接下载的地方了,请看
    wxf666
        4
    wxf666  
       2022-10-10 19:26:01 +08:00
    @blackantt 粗试了一下,Python 的正则是没问题的,因为在 regex101.comregexr.com 、Notedpad++ 等,都匹配到了相同的结果

    初步认为,你的正则出问题了
    liuidetmks
        5
    liuidetmks  
       2022-10-10 19:29:44 +08:00
    忘记哪看的,文法里面如果嵌套多个模糊匹配,消耗资源指数上升。
    wxf666
        6
    wxf666  
       2022-10-10 21:31:23 +08:00
    @liuidetmks 可能你说的是 [灾难性回溯]( https://zh.javascript.info/regexp-catastrophic-backtracking ) ?


    @blackantt 实在不想改你的正则了,你自己去 regex101.com ,把你的正则、html 丢进去,看看都匹配了 7 个啥吧

    帮你把正则改成这样,然后在左边选择 `ECMAScript (JavaScript)` 引擎,可以看到每个匹配 *(淡蓝色)* 及其各自的 6 个 `(.*?)` *(绿橙紫粉红绿)* 都长啥样:

    ```regex
    <div class="css-em857x"><a title="(.*?) profile" href="\/profile\/\d{6,8}">(.*?)<\/a><\/div><\/h4>(.*?)title="(.*?)"(.*?)<\/span><\/div><div class="MuiBox-root css-15ro776"><span aria-hidden="true" title="China" (.*?)1 shared interest: Languages &amp; Cultures<\/p><\/div><div class=
    ```


    写了段用 lxml 库的 xpath 功能抽取结果的 Python 代码:

    *( V 站排版原因,行首加了全角空格,记得删除)*

    ```python
    import lxml

    html = lxml.html.parse(r'C:\Users\dengz\Downloads\out8.txt')

    for node in html.xpath(
      '//div[@role="listitem" and '
      './/div[@class="MuiBox-root css-k008qs"]/*[2] and '
      './/p[contains(text(), "1 shared interest")]]'):
      n1 = node.xpath('.//a[text()]')[0]
      n2 = node.xpath('.//div[@class="MuiBox-root css-15ro776"][2]/span')[0]
      print([n1.get('href'), n1.text, n2.get('title')])
    ```
    ch2
        7
    ch2  
       2022-10-10 21:35:15 +08:00
    你需要的是一个语法分析器,别用词法分析工具干这种需求了
    pppguest3962
        8
    pppguest3962  
       2022-10-14 14:59:43 +08:00
    我个人感觉,在 python 里 re 效率要比 bs,lxml 里的 xpath 取值,速度上要麻利得多,
    html 的正则匹配从来都不是全文检索的,除非特征很明显并且不变,唯一。
    我一般的做法是 A 对象正则匹配全文 html 的可能范围,
    B 对象从 A 对象中正则匹配可能段落,
    C 对象从 B 对象中正则析出目标值,
    这样也比 bs ,lxml.xpath 取值速度要快
    而且每一步容错的空间也很大,好操作。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3107 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 10:49 · PVG 18:49 · LAX 02:49 · JFK 05:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.