2

私はPythonで作成されたWebクローラーを研究していますが、非常に単純なものに出くわしました。しかし、次のコードで強調表示されている最後の数行がわかりません。

import sys
import re
import urllib2
import urlparse

tocrawl = [sys.argv[1]]
crawled = []

keywordregex = re.compile('<meta\sname=["\']keywords["\']\scontent=["\'](.*?)["\']\s/>')
linkregex = re.compile('<a\s(?:.*?\s)*?href=[\'"](.*?)[\'"].*?>')

while 1:
    crawling = tocrawl.pop(0)
    response = urllib2.urlopen(crawling)
    msg = response.read()
    keywordlist = keywordregex.findall(msg)
    crawled.append(crawling)
    links = linkregex.findall(msg)
    url = urlparse.urlparse(crawling)

    a = (links.pop(0) for _ in range(len(links))) //What does this do?

    for link in a:
        if link.startswith('/'):
            link = 'http://' + url[1] + link
        elif link.startswith('#'):
            link = 'http://' + url[1] + url[2] + link
        elif not link.startswith('http'):
            link = 'http://' + url[1] + '/' + link

        if link not in crawled:
            tocrawl.append(link)

その行は私にはある種のリスト内包表記のように見えますが、よくわかりません。説明が必要です。

4

3 に答える 3

9

これはジェネレータ式linksであり、繰り返し処理するときにリストを空にするだけです。

彼らはこの部分を置き換えることができたでしょう

a = (links.pop(0) for _ in range(len(links))) //What does this do?

for link in a:

これとともに:

while links:
    link = links.pop(0)

そして、それは同じように機能します。ただし、リストの最後からポップする方が効率的であるため、次のいずれよりも優れています。

links.reverse()
while links:
    link = links.pop()

もちろん、リンクを逆の順序でたどることに問題がない場合(なぜそれらを順番に処理する必要があるのか​​わかりません)、linksリストを逆にせずに最後をポップする方がさらに効率的です。

于 2012-08-02T11:16:58.543 に答える
2

リンク リストからオブジェクトを取得するジェネレータを作成します。

説明する:

range(len(links))0 からリンク リストの長さまでの数値のリストを返します。したがって、リンクに が含まれている場合[ "www.yahoo.com", "www.google.com", "www.python.org" ]、リスト [0, 1, 2] が生成されます。

for _ in blah、リストをループして結果を捨てるだけです。

links.pop(0)リンクから最初の項目を削除します。

式全体は、リンク リストの先頭からアイテムをポップするジェネレータを返します。

最後に、Python コンソールでのデモ:

>>> links = [ "www.yahoo.com", "www.google.com", "www.python.org "]
>>> a = (links.pop(0) for _ in range(len(links)))
>>> a.next()
'www.yahoo.com'
>>> links
['www.google.com', 'www.python.org ']
>>> a.next()
'www.google.com'
>>> links
['www.python.org ']
>>> a.next()
'www.python.org '
>>> links
[]
于 2012-08-02T11:28:47.493 に答える
0
a = (links.pop(0) for _ in range(len(links)))

次のように書くこともできます:

a = []
for _ in range(len(links)):
    a.append(links.pop(0))

編集:

唯一の違いは、ジェネレーターを使用する場合は遅延して実行されるため、アイテムはaを介して要求されたときにのみリンクからポップされます。一度にすべてではありませんが、大量のデータを処理する場合ははるかに効率的であり、高度なpythonic関数を使用せずにこれを行う方法はありません。

于 2012-08-02T11:16:34.757 に答える