1. 程式人生 > >python實現與八爪魚圖片下載轉換器等效的爬蟲工具

python實現與八爪魚圖片下載轉換器等效的爬蟲工具

上週為了從網路上搜尋一些資料而接觸到了爬蟲,由於時間緊迫,不能從頭開始學習,就想從網上找一些現成的爬蟲工具直接使用,百度搜素得到的結果有這麼幾種:LoalaSam_Beta、火車頭、集搜客、八爪魚、沙漠之鷹等,第一個是外國的軟體,據說爬取國內的資料好像不好用;火車頭、集搜客、八爪魚這幾個軟體大同小異,都是不用寫程式碼,用視覺化的方法完成網頁上資料的採集,當然了,要自己制定一些採集規則,也就是設計流程圖。由於八爪魚這個軟體官方提供的學習資料和視訊課程比較多,而且也有免費版本,所以就用了1天時間學習這個軟體的使用並抓取到了一些資料。

遺憾的是,八爪魚只能直接採集到網頁上的文字資訊和圖片的連結,並不能直接將想要的圖片下載下來,如果要將圖片下載下來,就需要先用制定好的規則採集到圖片的URL,並將這些URL儲存到EXCEL中,在EXCEL中進行預處理後,在用八爪魚提供的某個圖片下載工具將URL對應的圖片下載下來。然而經過嘗試,八爪魚交流群裡下載到的那個圖片轉換工具貌似並不是他們自己公司開發的,而且我下載圖片並不能成功,只是簡單的生成了圖片的縮圖,但是圖片內容一個都沒有,根本就沒有什麼卵用。

後來沒辦法,覺得這個工具應該也沒有多高深,就抱著試試看的態度自己用python寫一個吧。要寫這樣個工具,首先要明確這個工具的目的是什麼,下面這張EXCEL表中存放的是要下載的圖片名稱、圖片的URL和圖片要儲存在本地的路徑。如下圖:


這張表裡,前兩列分別存放了要下載的圖片的名稱、圖片的URL,這兩列資料是用八爪魚從網頁上上爬來的,第三列中的圖片儲存路徑就是自己設定的了,這個如果量比較大的話,當然在EXCEL裡用函式是很好完成的了,先在C1單元格里寫上圖片要存放的那個資料夾的路徑,並在末尾加上“\”,然後自動填充,使這列中的檔案路徑相同;再在D1單元格中寫上“.jpg”,寫完後也自動填充該列;然後在E1單元中輸入公式“=C1&A1&D1

”,寫完敲回車,就出了要存放的圖片的包含名稱和字尾的全路徑,然後自動填充這列;最後,選中E列並將這列內容複製貼上到F列中,然後刪除掉C、D、E三列並儲存該EXCEL表,這樣,資料預處理的工作就完成了。下面介紹python寫爬蟲工具的過程:

想要的工具應該具有這樣的功能,它能自動讀取上面EXCEL檔案中的B列內容並作為URL來訪問網路,然後下載到對應的目標檔案並儲存到C列中對應的路徑下生成此目標檔案。這其實就涉及到兩方面的內容,一個是用python讀取EXCEL的操作,另一個就是用python下載檔案的操作。我們先解決用python下載檔案到本地的操作。

網上百度一下,說是有三種方法可以實現,

第一種:

import urllib

import urllib2

import requests

print "downloading with urllib"

url = "http://www.pythontab.com/test/demo.zip"

print "downloading with urllib"

urllib.urlretrieve(url,"demo.zip")

第二種:

import urllib2

print "donloading with urllib2"

url = "http://www.pythontab.com/test/demo.zip"

f = urllib2.urlope(url)

data = f.read()

with open("demo2.zip","web") as code:

    code.write(data)

第三種:

import request

print "downloading with requests"

url = "http://www.pythontab.com/test/demo.zip"

r = requests.get(url)

with open("demo3.zip","wb") as code:

    code.write(r.content)

第一種和第三種沒試過,直接用的第二種,url就用的B1單元格里的URL,demo2.zip處就是用的C1單元格里的內容替換的,測試一下,制定的路徑下果然生成了想要的那張圖片,這說明,用Python實現下載圖片的內容已經得到解決,下面的問題就是要解決批量下載了,那就得讓python去讀EXCEL檔案,遍歷並記錄B、C兩列的內容。百度一下python讀取EXCEL的方法,網上很多,比如這個連結裡講的,很簡練:http://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html,

1、匯入模組:import xlrd

2、開啟EXCEL檔案讀取資料:data = xlrd.open_workbook('excelFile.xls')

3、獲取一個工作表:(通過名稱獲取)table= data.sheet_by_name(u'Sheet1')

                                       (通過索引順序獲取)table= data.sheet()[0]

                                       (通過索引順序獲取)table = data.sheet_by_index(0)

4、獲取整行和整列的值(陣列):table.row_values(i)

                                                              table.col_values(i)

5、獲取行數和列數:nrows = table.nrows

                                      ncols = table.ncols

6、迴圈行列表資料:for i in range(nrows):

                                            print table.row_values(i)

7、單元格:cell_A1 = table.cell(0,0).value

                      cell_C4 = table.cell(2,3).value

8.使用行列索引:cell_A1 = table.row(0)[0].value

                               cell_A2 = table.col(1)[0].value

這些操作怎麼用都要去試,1、2、3步是肯定都要寫的,後面的步驟就要選擇性使用。現在我們想一行一行的遍歷Sheet1中的資料,然後將每行讀到的資料按A、B、C分成三部分,將B部分對應的值賦給URL,將C部分中對應的值賦給demo2.zip位置的變數。然後第一行就進行上面講到的python下載檔案操作,第一行下完儲存後開始第二行同樣的操作,然後是後面的每行,執行同樣的操作,直到遍歷完成所有的行,程式就結束了,也就下載完成所有的圖片並完成儲存。思路有了,下面開始實現:

import xlrd

import urllib.request

data = xlrd.open_workbook(r"C:\Users\85196\Desktop\PROT_AIN\AX_AIN.xlsx")

table = data.sheet_by_name(r"Sheet1")

for i in range(table.nrows):

      parrentrow = table.row_values(i)                             #可以print parrentrow用來測試返回的資料結構,發現返回的是一個列表,裡面存放了A1、B1、C1單元格里的三個元素

      ainmal = parrentrow[0]                                               #取出這行(當前行)第一個元素,取名為ainmal

      url = parrentrow[1]                                                      #取出當前行第二個元素,取名為url

     savepath = parrentrow[2]                                           #取出當前行第三個元素,取名為savepath

     f = urllib.request.urlopen(url)                                     #訪問並開啟B1中的URL

     data = f.read()                                                               #讀到的東西取名叫data

     with open(save,path,"wb") as code:                         #在C1路徑下寫入data的內容,如果沒有這個檔案即時建立一個    

            code.write(data)

上面這段程式碼測試一下,發現C1路徑下那個資料夾下不斷自動生成想要的圖片,這說明程式寫成功了。但是問題是,這樣並不知道有多少張片要下載,也不知道下載進度,即當前下載的是第幾張、還剩多少張、什麼時候下載完成等等,這樣程式要是中途卡了或者崩了都沒有提示,這個軟體就不好用。那就思考新增這些提示。

首先,想知道有多少張圖片要下載很容易,因為Sheet1中每一行就對應一張圖片,有多少行就有多少張圖片,所以只要獲取Sheet1的行數就行了,一句話 :                           print table.nrows.  

為了讓提示更人性化,這樣寫:

print "The total number of the picture to download is" + str(table.nrows)             #table.nrows是整型,要和前面連線先強轉成字串型

下面就是提示還剩多少張沒下載,這個怎麼弄呢?想一下,比如我們執行到第一行時候,肯定還剩  (table.nrows - 1)行沒執行,就是還剩這麼些圖片待下載;當我們執行到第8行時,就還剩(table.nrows - 8)多張沒下載;那用一個變量表示當前執行到的行數就行了, 我們上面的程式裡,i 這個變數,就和行數有關,它就表示Sheet1中的每一行,但是 i 得起始值是0,就是當下載第一張是,i = 0; 當下載第二張時,i = 1; 可知 i = 行數 - 1,所以直接用 (table.nrows - i  )得到的值就比 (table.nrows - 當前行數)的到的值少減了一個,那要用i表示正確的剩餘行數, 只需 再多減一個數,即用 (table.nrows - i - 1)來表示就行了。我們讓程式執行到每次開啟URL的時候提示出剩餘圖片的數目就行了。一句話:

print “The parent picture beeing download is ”  +  animal  +  "  , and " + str(table.nrows - i -1 ) + "pictures are rest!"                  #提示當前下載的是那張圖片,還剩多少張沒下載

再試一下,果然好使多了,但是還有一個問題,程式每次下載到一半不能進行了,重啟以後前面已經得到的圖片還要被重新下載而覆蓋,重新下載和替換的過程也是要花費時間的,那就有可能100張圖片永遠也下載不晚。我們想實現這樣的功能,每次程式重啟之後,自動識別一下目標路徑下是否已經存在同名的目標檔案,是的話就忽略掉重新下載它們的步驟,提示這張圖片已經存在,還剩多少張沒下載並直接從它們後面開始執行,並提示當前下載的圖片名稱和下載進度。要實現這樣的效果,我們肯定要做一個           if / else 的判斷,判斷的條件就是目標路徑下是否存在目標檔案,這可以用系統庫裡面的exists 函式來實現:os.path.exists(savepath),  這個函式返回的值是True 或 Flase , 如果返回True ,那就讓它忽略掉上面的下載步驟,直接提示那些檔案已存在; 如果返回Flase ,再讓它開始下載過程,並提示下載檔名稱和進度,這樣就實現了這個功能。下面上完整的程式碼,python 版本是3.5, 對中文註釋支援不好,註釋都用英文。程式碼如下:



測試一下,很好用,見如下效果:



右邊互動視窗會提示下載進度,要是程式卡住,半天不響應,就重啟程式,讓它從後面開始下載,也可以多重啟幾次直到全部下載完成。