V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
SingeeKing
V2EX  ›  问与答

正则表达式的 Catastrophic backtracking 错误

  •  
  •   SingeeKing · 2017-03-31 15:43:36 +08:00 · 1306 次点击
    这是一个创建于 2600 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在写 python 爬虫抓取 OPAC 的图书列表,有一段 HTML 如下

    <div class="bookmeta" bookrecno="166612">
                  <div>1 . 
                    <span class="bookmetaTitle">
                      <a href="book/166612" target="_blank">
                        数学百科全书.第一卷 A-C
                      </a>
                    </span>
                    <a href="book/166612" target="_blank">
                      <img border="0" src="/opac/media/images/newwin.png">
                    </a>
                  </div>
                  <div>著者:
                    <a href="/opac/search?searchWay=author&amp;q=%E3%80%8A%E6%95%B0%E5%AD%A6%E7%99%BE%E7%A7%91%E5%85%A8%E4%B9%A6%E3%80%8B%E7%BC%96%E8%AF%91%E5%A7%94%E5%91%98%E4%BC%9A%E7%BC%96%E8%AF%91" target="_blank"> 
                      《数学百科全书》编译委员会编译
                    </a>
                  </div>
                  <div>
                    出版社: 
                    <a href="/opac/search?searchWay=publisher&amp;q=%E7%A7%91%E5%AD%A6%E5%87%BA%E7%89%88%E7%A4%BE" target="_blank"> 
                      科学出版社
                    </a>
                    &nbsp;
                    出版日期: 1994
                  </div>
                  <div>
                    文献类型: 
                    
                    <img src="/opac/booktypeicon/1" class="booktypeIcon">
                    图书, 
                    索书号:
                    <span class="callnosSpan">O1-61/S661/:1 </span>
                  </div>
                </div>
    

    现在想要提取出内部的 书籍编号 (bookrecno) 书名索书号

    使用以下正则匹配,匹配到“索书号:”无问题

    <div class=\"bookmeta\" bookrecno=\"(\d*?)\">.*?<a href=\"book/\d*?\" target=\"_blank\">\s*(.*?)\s*</a>.*?索书号:
    

    但是想要继续匹配下面的 < 时,使用 \w*< 提示 “ Catastrophic backtracking 错误” 而 .*?< 却无任何问题。求解这个错误到底是什么?

    附:

    可以正常匹配的正则

    <div class=\"bookmeta\" bookrecno=\"(\d*?)\">.*?<a href=\"book/\d*?\" target=\"_blank\">\s*(.*?)\s*</a>.*?索书号:.*?<span class=\"callnosSpan\">\s*(.*?)\s*</span>.*?</div>.*?</div>
    

    提示错误的正则

    <div class=\"bookmeta\" bookrecno=\"(\d*?)\">.*?<a href=\"book/\d*?\" target=\"_blank\">\s*(.*?)\s*</a>.*?索书号:\w*<span class=\"callnosSpan\">\s*(.*?)\s*</span>\w*</div>\w*</div>
    
    5 条回复    2017-03-31 18:03:55 +08:00
    ijustdo
        1
    ijustdo  
       2017-03-31 16:44:57 +08:00   ❤️ 1
    python 里 正则库 \w 能匹配换行么?

    <div class=\"bookmeta\" bookrecno=\"(\d*?)\">.*?<a href=\"book/\d*?\" target=\"_blank\">\s*(.*?)\s*</a>.*?索书号:\s*<span class=\"callnosSpan\">\s*(.*?)\s*</span>\s*</div>\s*</div>

    出错的 改为这样就可以了 注意贪婪模式和非贪婪模式
    ijustdo
        2
    ijustdo  
       2017-03-31 16:46:41 +08:00
    还有一个技巧就是 不要每次都去编译正则 python 的正则可以 re.compile 编译为一个对象 然后用这个对象去 search 或者 match
    ltux
        3
    ltux  
       2017-03-31 17:36:35 +08:00 via Android   ❤️ 1
    又该上这个链接了
    http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/

    为什么不用 lxml 或者 beautiful soup 呢?
    SingeeKing
        4
    SingeeKing  
    OP
       2017-03-31 18:03:42 +08:00
    @ijustdo 嗯,谢啦;我就是用的 re.compile ,出错之后用 regex101 手动转义的
    SingeeKing
        5
    SingeeKing  
    OP
       2017-03-31 18:03:55 +08:00
    @SingeeKing 新手上路。。请多多关照😂
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1066 人在线   最高记录 6547   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 19:20 · PVG 03:20 · LAX 12:20 · JFK 15:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.