2017-02-11 86 views
0

有70%的機率會顯示錯誤:pool.map列表索引超出範圍巨蟒

res=pool.map(feng,urls) 
    File "c:\Python27\lib\multiprocessing\pool.py", line 251, in map 
    return self.map_async(func, iterable, chunksize).get() 
    File "c:\Python27\lib\multiprocessing\pool.py", line 567, in get 
    raise self._value 
IndexError: list index out of range 

不知道爲什麼,如果數據小於100,只有5%的機會表明message.any一個有想法如何改進?

#coding:utf-8 
import multiprocessing 
import requests 
import bs4 
import re 
import string 
root_url = 'http://www.haoshiwen.org' 

#index_url = root_url+'/type.php?c=1' 
def xianqin_url(): 
    f = 0 
    h = 0 
    x = 0 
    y = 0 
    b = [] 
    l=[] 


    for i in range(1,64):#頁數 
     index_url=root_url+'/type.php?c=1'+'&page='+"%s" % i 
     response = requests.get(index_url) 
     soup = bs4.BeautifulSoup(response.text,"html.parser") 
     x = [a.attrs.get('href') for a in soup.select('div.sons a[href^=/]')]#取出每一頁的div是sons的鏈接 
     c=len(x)#一共c個鏈接 
     j=0 
     for j in range(c): 
      url = root_url+x[j] 
      us = str(url) 
      print "收集到%s" % us 
      l.append(url) #pool = multiprocessing.Pool(8) 
    return l 

def feng (url) : 
    response = requests.get(url) 
    response.encoding='utf-8' 
#print response.text 
    soup = bs4.BeautifulSoup(response.text, "html.parser") 
#content = soup.select('div.shileft') 
    qq=str(soup) 
    soupout = re.findall(r"原文(.+?)</div>",qq,re.S)#以「原文」開頭<div>結尾的字段 
    #print soupout[1] 
    content=str(soupout[1]) 
    b="風" 
    cc=content.count(b,0,len(content)) 
    return cc 

def start_process(): 
    print 'Starting',multiprocessing.current_process().name 

def feng (url) : 
    response = requests.get(url) 
    response.encoding='utf-8' 
#print response.text 
    soup = bs4.BeautifulSoup(response.text, "html.parser") 
#content = soup.select('div.shileft') 
    qq=str(soup) 
    soupout = re.findall(r"原文(.+?)</div>",qq,re.S)#以「原文」開頭<div>結尾的字段 
    #print soupout[1] 
    content=str(soupout[1]) 
    b="風" 
    c="花" 
    d="雪" 
    e="月" 
    f=content.count(b,0,len(content)) 
    h=content.count(c,0,len(content)) 
    x=content.count(d,0,len(content)) 
    y=content.count(e,0,len(content)) 
    return f,h,x,y 


def find(urls): 
    r= [0,0,0,0] 
    pool=multiprocessing.Pool() 
    res=pool.map4(feng,urls) 
    for i in range(len(res)): 
     r=map(lambda (a,b):a+b, zip(r,res[i])) 
    return r 


if __name__=="__main__": 
    print "開始收集網址" 
    qurls=xianqin_url() 
    print "收集到%s個鏈接" % len(qurls) 
    print "開始匹配先秦詩文" 
    find(qurls) 
    print ''' 
    %s篇先秦文章中: 
--------------------------- 
    風有:%s 
    花有:%s 
    雪有:%s 
    月有:%s 
    數據來源:%s 
    ''' % (len(qurls),find(qurls)[0],find(qurls)[1],find(qurls)[2],find(qurls)[3],root_url) 

stackoverflow:身體不能包含「池ma p」。 將其更改爲res = pool.map4(feng,url) 我試圖從本網站獲取一些子字符串,並進行多處理。

+1

我們不能真正幫助你,除非你A)給我們代碼,並B)解釋它想做什麼... – Toastrackenigma

+0

我試過了,系統說我寫了太多的代碼,我會嘗試上傳圖片。 –

+0

代碼上傳.. –

回答

0

事實上,multiprocessing使調試有點困難,因爲您看不到index out of bound錯誤發生的位置(錯誤消息使其看起來好像在multiprocessing模塊內部發生)。

在某些情況下,這行:

content=str(soupout[1]) 

引發index out of bound,因爲soupout是一個空列表。如果您將其更改爲

if len(soupout) == 0: 
    return None 

,然後通過改變

res=pool.map(feng,urls) 

刪除已返回的None

res = pool.map(feng,urls) 
res = [r for r in res if r is not None] 

那麼就可以避免錯誤。這就是說。你可能想找出爲什麼re.findall返回一個空列表的根本原因。這當然是一個更好的主意與beatifulsoup比正則表達式來選擇節點,作爲一般的匹配與bs4更加穩定,特別是如果網站稍稍改變自己的標記(如空格等)

更新

why is soupout is an empty list? When I didn't use pool.map never I have this error message shown

這可能是因爲您敲擊Web服務器的速度太快。在評論中你提到你有時在response.status_code得到504。 504表示Gateway Time-out: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server

這是因爲haoshiwen.org似乎是由kangle驅動的,這是一個反向代理。現在,反向代理會處理您將其發送到Web服務器後面的所有請求,並且如果您現在一次啓動過多的進程,那麼可憐的Web服務器無法處理洪水。康樂has a default timeout of 60s,所以一旦他在60秒內沒有從網絡服務器得到答案,他就會顯示你發佈的錯誤。

你如何解決這個問題?

  • ,你可以限制的進程數:pool=multiprocessing.Pool(2),你需要有一個良好的許多過程
  • feng(url)頂部周圍玩,你可以添加一個time.sleep(5)所以每個進程等待每間隔5秒鐘請求。在這裏你也需要玩一下睡眠時間。
+0

非常感謝,我稍後再嘗試 –

+0

它的工作,但我仍然不知道爲什麼湯流是一個空列表,當我沒有我們'pol地圖func',從來沒有這個顯示的錯誤信息 –

+0

這可能是因爲你太快地處理web服務器,所以它返回'50x'響應代碼或帶有'200'的頁面並顯示錯誤。試試'print(response.status_code)'裏面的'if len(湯圓)== 0'塊 – hansaplast