2012-11-26 3 views
0

나는 각 레코드 20 개씩의 테이블에서 약 400,000 개의 레코드를 긁는 프로젝트 작업을하고 있습니다. 현재 스크립트는 페이지의 전체 URL 목록을 작성한 다음 각 URL에 대해 페이지를 열고 BeautifulSoup로 표를 찾고 각 행을 스크랩합니다. 그것은 각 행을 긁는 것처럼 그것은 CSV에 행을 기록 : 나는 각 행을 쓰는 한 번에 대신 CSV로 결과의 각 페이지를 쓴 경우이보다 효율적으로 할 것인지 궁금 해요테이블 긁고 행을 CSV로 작성

def scrape_table(url): 
    soup = get_soup(url) 
    table = soup.find('table' , {'id' : 'BigTable'}) 
    for row in table.find_all('tr'): 
     cells = row.find_all('td') 
     if len(cells) > 0: 
      name_bits = cells[0].get_text().strip().split(',') 
      first_name = name_bits[0].strip() 
      last_name = name_bits[1].strip() 
      species = cells[1].get_text().strip() 
      bunch = re.sub(u'[\xa0\xc2\s]+',' ',str(cells[5]),flags=re.UNICODE).strip() 
      bunch_strings = list(BeautifulSoup(bunch).td.strings) 
      weight = bunch_strings[1].strip() 
      bunch_match = re.match("dob:(.*) Mother: \$(.*)",bunch_strings[2].strip()) 
      dob = date_format(bunch_match.groups()[0].strip()) 
      mother = bunch_match.groups()[1].strip()    
      row_of_data = { 
       'first_name': first_name, 
       'last_name' : last_name, 
       'species' : species, 
       'weight' : weight, 
       'dob'  : dob, 
       'mother' : mother 
      } 
      data_order = ['first_name', 'last_name', 'dob', 'mother', 'weight', 'kesavan'] 
       csv_row(row_of_data,data_order,'elephants') 
     else: 
      continue 

def csv_row(data,fieldorder,filename, base=__base__): 
    full_path = __base__+filename+'.csv'  
    print "writing", full_path 
    with open(full_path, 'a+') as csvfile: 
     linewriter = csv.DictWriter(csvfile, fieldorder, delimiter='|', 
           quotechar='"', quoting=csv.QUOTE_MINIMAL) 
     linewriter.writerow(data) 

. 아니면 더 많은 RAM을 사용하고 나머지 컴퓨터 속도를 느리게합니까? 이것을보다 효율적으로 만드는 다른 방법은?

답변

1
with open(full_path, 'a+') as csvfile: 
    linewriter = csv.DictWriter(csvfile, fieldorder, delimiter='|', 
          quotechar='"', quoting=csv.QUOTE_MINIMAL) 
    linewriter.writerow(data) 

은 성능 저하 요인입니다. 파일 이름을 만들고, 파일을 열고, 객체를 구성하고, 디스크에 데이터를 쓰고, 파일을 다시 닫아야합니다. 모든 행의에 대해 을 다시 작성해야합니다. 즉 최소한 세 건의 시스템 호출을 수행하고 디스크 드라이버/컨트롤러가 "파일을 닫고 성공적으로 플러시"신호를 기다릴 것을 의미합니다.

적어도 전체 프로세스 중에 파일을 열어 두는 것이 좋습니다. 그 메모리 비용은 무시할 정도입니다. 그래서,

def scrape_table(url, linewriter): 
    # do scraping to get data 
    linewriter.writerow(data) 

그리고 아무것도 진정되지 않는 더 많은 RAM을 사용하여, 일반적으로

와 그를 호출합니다. 캐시를 다시 계산하는 대신 RAM에 캐시하는 것은 아마도 일반적인 최적화 기술입니다.

+1

파일을 열어 두어도 추가 모드로 열 필요는 없습니다. – martineau

+0

@martineau 좋은 지적. 비록 내가 알파벳의 덩어리 위에 그것을 실행하고 있었으므로, 추가 할 필요가있다. – Amanda

관련 문제