2014-01-09 6 views
0

내 웹 크롤러의 문제와 파이썬에 대한 urlparse 플러그인을 보내고 있습니다. 내 코드는 기본적으로 블룸버그 (Bloomberg)와 같은 특정 도메인을 크롤링하고 모든 HTML을 내 데스크톱으로 다운로드합니다. 아직 초기 단계에 있으므로 오류 등이 있음을 알게 될 것입니다. (저는 파이썬을 처음 사용합니다.)웹 크롤러 오류 : "AttributeError : 스파이더 인스턴스가 '발견'에는 속성이 없습니다"

특정 문제는 reconstruct_url과 관련이 있습니다. 나는 urlparse.urljoin(a,b) 기능을 개별적으로 테스트했으며 기대했던대로 작동하지만이 클래스에서는이 기능이 마음에 들지 않습니다. 어떤 사람이 여기에 문제가 무엇인지 보여줄 수 있습니까? 다른 문제뿐만 아니라 그들을 밖으로 소리 주시기 바랍니다 내 코드에서 당신에게 눈부시게 명백한 경우

이 전체 프로그램을 작성에서 내 첫 번째 시도이다. 비록 이것이 비교적 초기 단계에 있음을 유의하십시오. 어떤 도움을 주셔서 감사합니다.

#note: <meta content='Story' property='bb:resource_type'> 

import urllib2 
import os 
from bs4 import BeautifulSoup 
from urlparse import urljoin 

class Spider: 

    links_to_crawl = [] 
    crawled_links = [] 
    ignored_links = ['/'] 
    domain = 'http://bloomberg.com/' 
    #meta type = ('meta', {'property','bb:resource_type'})['content']=='Story' 

    # append all starting link to links_to_crawl 
    def __init__(self, url): 
     print 'Spider initialising...' 
     self.links_to_crawl.append(url) 

    # open input url and return html 
    def grab_html(self,url): 
     open_url = self.urllib2.urlopen(url) 
     data = open_url.read() 
     open_url.close() 
     return data 

    # return title from input html for file naming and ensure 
    # no '/' present in title. 
    def get_title(self, data=''): 
     title_start = data.find('<title>')+7 
     title_end = data.find('</title>')-1 
     title = data[title_start:title_end] 
     title = title.translate(None, '/') 
     return title+".txt" 

    # return date from input html for file saving structure 
    def get_date(self, data=''): 
     soup = self.BeautifulSoup(data) 
     # try statement to avoid error when meta tag combinations 
     # not found. 
     try: 
      date = soup.find('meta', {'name':'pubdate'})['content'] 
      return date[:12] # !! only tested with bloomberg.com !! 
     # if there is no published date, return 'Other' 
     except TypeError: 
      return 'Other' 

    # if link is relative url return 'Rel' or 
    # if url is allowed domain return 'Abs', else False. 
    def url_type(self,url=''): 
     if url[0:4] != 'http': 
      return 'Rel' 
     elif url.find(self.domain) != -1: 
      return 'Abs' 
     else: 
      return False 

    # reconstruct relative url 
    def reconstruct_url(self, page='', rel=''): 
     print page #debug 
     print rel #debug 
     print self.urljoin(page, rel) #debug 
     return self.urljoin(page, rel) 

    # get all links in input html and append to links_to_crawl 
    # unless in crawled_links or ignored_links 
    # if link is relative url reconstruct url and append to 
    # links_to_crawl, append relative url to ignored_links 
    def get_links(self, data=''): 
     soup = self.BeautifulSoup(data) 
     for link in soup.find_all('a'): 
      # try statement to avoid error when finding 
      # <a> tags withou 'href' 
      try: 
       if link['href'] in self.ignored_links or self.crawled_links: 
        pass 
       else: 
        if self.url_type(link['href'])=='Rel': 
         reconstructed_link = self.reconstruct_url(self.domain, link['href']) #to change !!!!!!!!!!!!!!!!! 
         self.links_to_crawl.append(reconstructed_link) # append reconstructed link to links_to_crawl 
         self.ignored_links.append(link['href']) # append original link to ignored_links 
        else: 
         self.links_to_crawl.append(link['href']) 
      except KeyError: 
       pass 

    # if directory exists do nothing 
    # if directory does not exist write directory 
    def ensure_dir(self, directory=''): 
     if self.os.path.exists(directory): 
      pass 
     else: 
      self.os.makedirs(directory) 

    # ensure the html being saved is the type requested 
    # currently only compatible with 1 meta type 
    def ensure_meta_type(self, data=''): 
     soup = self.BeautifulSoup(data) 
     try: 
      soup.find('meta', {'property':'bb:resource_type'})['content']=='Story' 
      print 'True' 
      return True 
     except TypeError: 
      print 'False' 
      return False 

    # save input html to txt file on mac os desktop and return 
    # absolute path to file 
    def save_html(self,data=''): 
     if self.ensure_meta_type(data): 
      print 'SAVING URL' 
      # allocate save path for file and ensure save path exists 
      save_path = self.os.path.abspath('/Users/sampeka/Desktop/Python Spider'+'/'+self.get_date(data)) 
      self.ensure_dir(save_path) 
      # get file name and write file to absolute path 
      file_name = self.get_title(data) 
      absolute_path = save_path+'/'+file_name 
      opened_file = open(absolute_path,'w') 
      opened_file.write(data) 
      opened_file.close() 
     else: 
      pass 



    # crawl links_to_crawl and pop to crawled_links list 
    # if ValueError then pop to ignored_links 
    # except urllib2.URLError to avoid web crawler crawling 
    # non-url links 
    def crawl_links(self): 
     while len(self.links_to_crawl) > 0: 
      url = self.links_to_crawl[0] 
      print url 
      try: 
       data = self.grab_html(url) 
       self.get_links(data) 
       self.save_html(data) 
       self.crawled_links.append(self.links_to_crawl.pop(0)) 
      except (ValueError, self.urllib2.URLError): 
       self.ignored_links.append(self.links_to_crawl.pop(0)) 
     print 'Spider finished.' 
     print 'Ignored links:' 
     print self.ignored_links 
     print 'Crawled links:' 
     print self.crawled_links 


spider = Spider('http://www.bloomberg.com/news') 
spider.crawl_links()  
+0

코드를 약간 닦았습니다. – twil

+0

대단히 감사합니다 :) –

답변

1

here는 코드의 DIFF이며, 그들 모두에 대한 코드를 수정했습니다.

+0

대단히 감사합니다. –

+0

귀하의 환영이지만, 투표는 더욱 고귀합니다. –

+0

나는 둘 다 투표했지만 불행히도 충분한 명성을 얻지 못했습니다. –

1

귀하의 reconstruct_url() 당신이 정의되지 않은 메서드를 Spiderself.urljoin를 사용하려고하기 때문에 작동하지 않습니다. 그냥 당신이 urlparse에서 가져온 기능을 사용 @twil가 언급 한 바와 같이 또한 당신이 다른 모듈에 대한 self를 사용하고,

# reconstruct relative url 
def reconstruct_url(self, page='', rel=''): 
    print page #debug 
    print rel #debug 
    print urljoin(page, rel) #debug 
    return urljoin(page, rel)