之前在做爬蟲的時候遇到一種情況,當網絡情況不太好的時候,爬蟲爬到的鏈接在urlopen時會因為無法正常連接而報URLError或者timeout的錯誤導致陳序報錯而終止;但是這些錯誤在重新運行陳序后能夠解決,因此為了避免重復手動重啟程序的麻煩,就想寫腳本來自動重啟。
思路很簡單:
1.首先腳本檢測目標程序是否在運行。這里我們可以用pidof的返回值來判斷。
2.如果腳本檢測到程序尚未運行或程序運行出錯,重啟程序。這里需要用到linux的$?變量,該變量能返回上一次命令的運行狀態。其中0為運行正常,其他均為運行報錯。
3.如果程序正常運行結束,終止腳本
例如我們要自動運行名為web_crawler.py的腳本,那么可以寫如下shell腳本:
#! /bin/bash
pidof web_crawler.py # 檢測程序是否運行
while [ $? -ne 0 ] # 判斷程序上次運行是否正常結束
do
echo "Process exits with errors! Restarting!"
python web_crawler.py #重啟程序
done
echo "Process ends!"
PS1: 這只能處理網絡狀況不良引起連接出錯的情況,通過重新嘗試鏈接能夠解決的。如果是遇到了由於網站被牆導致的鏈接錯誤,那么這個做法就很有問題了,因為無論你重復幾次都無法打開鏈接。這種情況的解決方式要么是翻牆再運行爬蟲,那么就是跳過被牆的鏈接——具體操作可以是用re匹配鏈接排除,也可以是用try在連接超時執行跳出操作。例如:
try:
res = urllib2.urlopen(rq, timeout=10) # use urllib2 package
except urllib2.URLError, e:
print "Timed out to connect to this URL"
return None
except socket.timeout: # use socket package
print "Time out!"
return None
PS2:這里我們實際爬的是stanford cs224d上的鏈接然后下載內容,由於有些鏈接(pdf文件或者html網頁)不包含文件后綴,保存的時候會比較麻煩。但是如果鏈接是網頁的話那么res.headers.getheader('Content-Type') # urllib2或者rq = requests.get(url);r.headers['content-type'] # requests返回內容包含'text/html',利用這一點我們就可以識別出網頁鏈接進行保存。
參考:
- http://stackoverflow.com/questions/18883086/check-if-the-page-is-html-page-in-python
- http://stackoverflow.com/questions/20162678/linux-script-to-check-if-process-is-running-act-on-the-result
- http://stackoverflow.com/questions/90418/exit-shell-script-based-on-process-exit-code
- http://stackoverflow.com/questions/16778435/python-check-if-website-exists
