我正在尝试使用python实现Web爬虫。 以下是我到目前为止的情况:
import urllib2
seed=raw_input('Enter a url : ')
def getAllNewLinksOnPage(page,prevLinks):
response = urllib2.urlopen(page)
html = response.read()
links,pos,allFound=[],0,False
while not allFound:
aTag=html.find("<a href=",pos)
if aTag>-1:
href=html.find('"',aTag+1)
endHref=html.find('"',href+1)
url=html[href+1:endHref]
if url[:7]=="http://":
if url[-1]=="/":
url=url[:-1]
if not url in links and not url in prevLinks:
links.append(url)
print url
closeTag=html.find("</a>",aTag)
pos=closeTag+1
else:
allFound=True
return links
toCrawl=[seed]
crawled=[]
while toCrawl:
url=toCrawl.pop()
crawled.append(url)
newLinks=getAllNewLinksOnPage(url,crawled)
toCrawl=list(set(toCrawl)|set(newLinks))
print crawled
我想知道如何实施深度搜索并对结果进行排序。
答案 0 :(得分:4)
到目前为止,您实施的是一种随机顺序搜索,因为您要保留set
个抓取链接。 (你实际上是保留list
,但是反复将它转换为set
,这会扰乱你的任何顺序。)
要将其转换为深度优先搜索,通常的解决方案是递归执行。然后,您不需要任何外部存储链接来进行爬网。您做仍然需要跟踪到目前为止已爬网的链接 - 两者都是为了避免重复,并且因为您想要在最后对链接进行排序(这需要对某些内容进行排序),但就是这样。所以:
def crawl(seed):
crawled = set()
def crawl_recursively(link):
if link in crawled:
return
newLinks = getAllLinksOnPage(link)
crawled.add(seed)
for link in newLinks:
crawl_recursively(link)
crawl_recursively(seed)
return sorted(crawled)
如果您不想使用递归,则替代方法是使用显式堆栈链接进行爬网。但你不能继续重组那个堆栈,或者它不再是堆栈。同样,一组单独的已爬行链接将解决避免重复查找的问题。
def crawl(seed):
crawled = set()
to_crawl = [seed]
while to_crawl:
link = to_crawl.pop()
if link in crawled:
continue
crawled.add(link)
newLinks = getAllLinksOnPage(link)
to_crawl.extend(newLinks)
return sorted(crawled)
将堆栈转换为队列(只需将一行更改为to_crawl.pop(0)
),这将成为广度优先搜索。
如果你担心to_crawl
变得太大,因为它充满重复,你可以随时将它们剥离。既然你想要深度优先,你想要去除那些以后堆积的,而不是新的。最简单的方法是使用OrderedSet
(例如recipe文档中链接的collections
):
to_crawl = OrderedSet()
# …
new_link_set = OrderedSet(newLinks)
to_crawl -= new_link_set
to_crawl |= new_link_set - crawled