2011-06-02 2 views
1

多数のページ(たとえば1000)を解析し、リンクをtinyurlリンクに置き換える必要があります。 Pythonのページのリンクを高速に解析する

は今、私は正規表現

href_link_re = re.compile(r"<a[^>]+?href\s*=\s*(\"|')(.*?)\1[^>]*>", re.S) 

を使用して、これをやっているが、その十分に速くありません。

私はこれまで

  1. ステートマシンを考えています

は、あなたがより速くを提案できるHTMLパーサーを使用して

  • (これの成功は巧妙なコードを書くために私の能力に依存します)方法ですか?

    EDIT: あなたは、HTMLパーサが速く正規表現よりもだろうと思うだろうが、私のテストではありません:

    from BeautifulSoup import BeautifulSoup, SoupStrainer 
    
    import re 
    import time 
    
    __author__ = 'misha' 
    
    regex = re.compile(r"<a[^>]+?href\s*=\s*(\"|')(.*?)\1[^>]*>", re.S) 
    
    def test(text, fn, desc): 
    
        start = time.time() 
        total = 0 
        links = []; 
        for i in range(0, 10): 
         links = fn(text) 
         total += len(links) 
        end = time.time() 
        print(desc % (end-start, total)) 
        # print(links) 
    
    def parseRegex(text): 
        links = set([]) 
        for link in regex.findall(text): 
         links.add(link[1]) 
        return links 
    
    def parseSoup(text): 
        links = set([]) 
        for link in BeautifulSoup(text, parseOnlyThese=SoupStrainer('a')): 
         if link.has_key('href'): 
          links.add(link['href']) 
    
        return links 
    
    
    
    if __name__ == '__main__': 
        f = open('/Users/misha/test') 
        text = ''.join(f.readlines()) 
        f.close() 
    
        test(text, parseRegex, "regex time taken: %s found links: %s") 
        test(text, parseSoup, "soup time taken: %s found links: %s") 
    

    出力:

    regex time taken: 0.00451803207397 found links: 2450 
    soup time taken: 0.791836977005 found links: 2450 
    

    (テストはAですウィキペディアのフロントページのダンプ)

    私はスープをひどく使っているに違いありません。 何が間違っているのですか?

  • +0

    最初に ' GWW

    +0

    はい、それはステートマシンのルートになります – mkoryak

    +0

    なぜHTMLパーサーは正規表現より高速でしょうか?さらに、BeautifulSoupは主にPythonコードですが、reモジュールはCです。 – susmits

    答えて

    2

    おそらく、このタスクにはLXMLが最適です。 Beautiful Soup vs LXML Performanceを参照してください。 LXMLではリンクの解析が簡単で高速です。

    root = lxml.html.fromstring(s) 
    anchors = root.cssselect("a") 
    links = [a.get("href") for a in anchors] 
    
    1

    regexpの非常に悪い考えを使用して解析すると、スピードとregexpの指数関数時間の問題が原因です。 代わりにxhtmlにパーサーを使用できます。最高はLXMLです。 または、この目的のためにLL、LRパーサを使ってパーサを特別に書くことができます。たとえば、ANTLR,YAPPS,YACC,PYBISONなど

    +2

    htmlを解析するために正規表現を使用することを含む質問が投稿されるたびに、この伝説の投稿を覚えています。 http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags – Aphex

    +0

    より速いのはどれですか:LXMLまたは美味しいスープ?私は後者を使用してきましたが、最近は頻繁に推奨されているようです。 – jhocking

    +0

    LXMLはネイティブパーサーですが、Beautiful Soupは解析にreg expsを使用しています。 LXMLが優れています。 –