2012-11-26 58 views
0

我正在處理一個項目,每個項目在20個記錄的表中擦除約400,000條記錄。目前,我的腳本爲頁面創建了一個完整的URL列表,然後爲每個URL打開頁面,使用BeautifulSoup查找表格並擦除每一行。由於它刮掉每一行吧行寫入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) 

我想知道如果,如果我寫的每一結果頁到CSV一次,而不是寫每一行的,這將是更有效的。或者是否會使用更多內存並減慢我的其他計算機?其他方法可以提高效率?

回答

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