我正在研究用Python制作的网页抓取工具,我偶然发现了一个非常简单的网页抓取工具。但是,我不理解最后几行,在以下代码中突出显示:
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)
这条线对我来说看起来像某种列表理解,但我不确定,我需要解释。
答案 0 :(得分:9)
这是一个generator expression,当您迭代它时,它会清空列表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
列表会更有效率然后弹出结束。
答案 1 :(得分: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
[]
答案 2 :(得分:0)
a = (links.pop(0) for _ in range(len(links)))
也可以写成:
a = []
for _ in range(len(links)):
a.append(links.pop(0))
修改强>
唯一的区别是当使用生成器时它是懒惰地完成的,所以只有通过链接请求才能从链接中弹出项目。而不是一次性,当处理大量数据时,它会更有效率,并且没有使用高级pythonic函数就无法做到这一点。