2011-07-20 212 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 ...