2011-07-20 130 views
0

所以我正在寻找一种动态的方式来抓取一个网站,并从每个页面抓取链接。我决定尝试Beauitfulsoup。两个问题:我如何更动态地执行此操作,然后使用嵌套while语句搜索链接。我想从本网站获取所有链接。但我不想继续嵌套while循环。使用python来抓取一个网站

topLevelLinks = self.getAllUniqueLinks(baseUrl) 
    listOfLinks = list(topLevelLinks)  

    length = len(listOfLinks) 
    count = 0  

    while(count < length): 

     twoLevelLinks = self.getAllUniqueLinks(listOfLinks[count]) 
     twoListOfLinks = list(twoLevelLinks) 
     twoCount = 0 
     twoLength = len(twoListOfLinks) 

     for twoLinks in twoListOfLinks: 
      listOfLinks.append(twoLinks) 

     count = count + 1 

     while(twoCount < twoLength): 
      threeLevelLinks = self.getAllUniqueLinks(twoListOfLinks[twoCount]) 
      threeListOfLinks = list(threeLevelLinks) 

      for threeLinks in threeListOfLinks: 
       listOfLinks.append(threeLinks) 

      twoCount = twoCount +1 



    print '--------------------------------------------------------------------------------------' 
    #remove all duplicates 
    finalList = list(set(listOfLinks)) 
    print finalList 

我的第二个问题是有无论如何告诉我是否有从网站的所有链接。请原谅我,我对Python有点新(大约一年),我知道我的一些流程和逻辑可能是幼稚的。但我必须以某种方式学习。主要我只是想使用嵌套while循环来做到这一点更加动态。预先感谢您的任何见解。

+1

为什么不能你是不是只用一个数组作为所有链接的累加器,然后在你发现网站上有更多的时候把它们排队呢? –

+0

好的,好主意。我将如何继续寻找更多。上面的代码只在页面树中向下三级。我想让这个更动态,然后嵌套循环 – hackthisjay

+1

你不需要嵌套。通过页面的html运行一次,并有一个所有链接的数组。然后通过下一个链接。除非你想深度优先,那么为什么你不使用递归函数,尽管最终它会溢出堆栈......网络很大:O –

回答

4

蜘蛛爬过网站并获取所有链接的问题是一个常见问题。如果Google搜索“蜘蛛网站python”,你可以找到能为你做到这一点的库。这里有一个我发现:

http://pypi.python.org/pypi/spider.py/0.5

更妙的是,谷歌发现这个问题已经提出和回答在这里StackOverflow上:

Anyone know of a good Python based web crawler that I could use?

+0

我最初在StackOverflow上看过那篇文章,并决定使用BeautifulSoup + urllib2。但主要问题是,如何让这些嵌套的while循环更具动态性。我会看看spider.py。感谢您的信息 – hackthisjay

0

要回答评论你的问题,这里有一个例子(这是红宝石,但我不知道蟒蛇,他们足够相似,你可以轻松地跟随):

#!/usr/bin/env ruby 

require 'open-uri' 

hyperlinks = [] 
visited = [] 

# add all the hyperlinks from a url to the array of urls 
def get_hyperlinks url 
    links = [] 
    begin 
    s = open(url).read 
    s.scan(/(href|src)\w*=\w*[\",\']\S+[\",\']/) do 
     link = $&.gsub(/((href|src)\w*=\w*[\",\']|[\",\'])/, '') 
     link = url + link if link[0] == '/' 

     # add to array if not already there 
     links << link if not links =~ /url/ 
    end 
    rescue 
    puts 'Looks like we can\'t be here...' 
    end 
    links 
end 

print 'Enter a start URL: ' 
hyperlinks << gets.chomp 
puts 'Off we go!' 
count = 0 
while true 
    break if hyperlinks.length == 0 
    link = hyperlinks.shift 
    next if visited.include? link 
    visited << link 
    puts "Connecting to #{link}..." 
    links = get_hyperlinks(link) 
    puts "Found #{links.length} links on #{link}..." 
    hyperlinks = links + hyperlinks 
    puts "Moving on with #{hyperlinks.length} links left...\n\n" 
end 

对红宝石抱歉,但它更好的语言:P,不应该很难适应,或者像我说的,理解。

+0

红宝石没有问题,我不得不学习一点使用Watir – hackthisjay

0

1)在Python中,我们不计算容器的元素并使用它们来索引;我们只是遍历其元素,因为这就是我们想要做的。

2)为了处理环节多层次的,我们可以使用递归。

def followAllLinks(self, from_where): 
    for link in list(self.getAllUniqueLinks(from_where)): 
     self.followAllLinks(link) 

这不处理链接的周期,但原始方法也没有。您可以通过随时建立已访问链接的set来处理该问题。

+0

如何使用您提交的这种方法构建一组已经访问过的链接。这是正确的道路。非常感谢 – hackthisjay

0

使用scrapy

Scrapy是一个快速的高层次的屏幕抓取和Web爬行 框架,用来抓取网站,并从 自己的网页中提取结构化数据。它可以用于广泛的用途,从数据采集到监测和自动化测试。

2

如果使用BeautifulSoup,为什么不使用findAll()方法?基本上,在我的履带我做:

self.soup = BeautifulSoup(HTMLcode) 
for frm in self.soup.findAll(str('frame')): 
try: 
    if not frm.has_key('src'): 
     continue 
    src = frm[str('src')] 
    #rest of URL processing here 
except Exception, e: 
    print 'Parser <frame> tag error: ', str(e) 

帧标签。 “img src”和“a href”标签也是如此。 虽然我喜欢这个话题 - 也许这是我的错误...... 编辑:有一个顶级实例,它保存了URL并从以后的每个链接获取HTMLcode ...