好了,開始上課(好像並沒有人,但是沒關係,我就是這麼自嗨。)

開始要說明我的操作環境,如果你和我的不一樣,請閱讀本文的時候注意代碼的差別:

  1. python版本:3.6.1
  2. scrapy版本:1.3.2
  3. 編譯器:pycharm 2017.1.1

首先要說的是,scrapy的原理我不講,自己領會(其實我也講不出什麼,網上一堆一堆的,講的都跟我想說的一樣,筆芯。)

然後開始進入正題。你需要了解scrapy是一個第三方庫,運行開始前,你需要在本機安裝scrapy,現在scrapy對windows平台也十分友好了(也許是最新版更友好了),或者是因為我安裝了virtual studio 2015的原因,因為有一些bat腳本是scrapy的依賴庫比如twisted所需要的。

virtual studio 2015就是下圖所示軟體(當然,我沒有激活,但是不影響對各種python第三方工具的安裝,雖然它體積大的驚人):

你可以查看網上各種各樣的scrapy安裝教程以及各種填坑指南,但是因為我可能是安裝了以上的編譯器,安裝異常順利。

打開cmd,然後執行命令

pip install scrapy

安裝完成,就這這麼簡單。

當然,其實我是更懶的。

我一般都是打開pycharm->File->Settings...->Project:xxx->Project Interpreter->"+"->搜索"scrapyt"進行安裝。這個方法簡單快捷,更主要的是,如果你有虛擬環境,對虛擬環境的切換也是如絲般順滑。

安裝成功之後,就是新建工程了。

在我學習python的過程中,只有scrapy和django是直接建立工程,通過工程進行程序的運行(如果你知道更多的,你可以私信告訴我,現在請配合我假裝不知道這回事。)

新建工程這回事也沒什麼困難的,就是在cmd中敲一條命令。

scrapy startproject meitulu

注意:新建的工程在當前目錄下,請確認想要保存的路徑。

敲完命令的效果如下圖所示(我是用的是pycharm中的終端,效果和CMD是一樣的):

新建完成之後的目錄結構如下圖所示(還是pycharm中顯示的結構):

建立完工程後,你可以看到終端中提示了你怎麼建立一個簡單的爬蟲文件。

按照終端中提示的進行操作:

cd meitulu
scrapy genspider mtl meitulu.com

終端中顯示如下圖所示:

可以看到提示已經在spider目錄下創建了一個文件,目錄結構現在如下所示:

打開mtl.py,可以看到如所示:

其中,MtlSpider是類名,不用管,可以隨便起沒有影響(如果你不明白什麼是類,請再鞏固一下python基礎知識)。name是爬蟲唯一標識,需要唯一,不能重複(後期很多爬蟲的時候,你可能會寫很多名字,每個名字都不能重複),allow_domins是允許爬取的目標網站的域名,大概下一篇文章你就知道作用是什麼了,這裡先買一個關子(本來是想在這篇文章中寫的,但是我還是太懶了,哈哈哈,ran)。start_urls是開始爬取的url網址。parse是爬取目標網站後的處理程序,parse中的response是目標網站回應的信息,包括頭、狀態、回應主體等等。

我們需要爬取的是美圖錄的一個類別,網址是:

http://www.meitulu.com/guochan/

修改mtl.py 將start_urls替換為以下方法:

def start_requests(self):
if os.path.exists(os.path.join(os.getcwd(), "meitulu/target.html")):
url = "file:///%s" % os.path.join(os.getcwd(), "meitulu/target.html")
else:
url = "http://www.meitulu.com/guochan/"
yield scrapy.Request(url=url, callback=self.parse)

start_urls和start_requests都是開始進行爬取的url,不同的是一個是變數一個是方法(廢話)。

可以看到我上面使用了os模塊,os模塊是python自帶的模塊,不需要安裝,只要進行導入就行。

import os

os.path.exists(dir)的含義是dir是否存在,存在則為True,不存在則為False,os.path.join()的含義是將內部的路徑進行拼接,而os.getcwd()的意思是獲取當前路徑。

這句話(os.path.exists(os.path.join(os.getcwd(), "meitule/target.html")))整體的意思就是看scrapy路徑下的meitule目錄中是否含有target.html緩存。至於為什麼需要緩存,請參考python爬蟲之scrapy掃盲:搜集美圖信息之先發一些牢騷(0) - 知乎專欄這篇文章。

可以看到,start_requests最後使用了回調函數parse(默認就使用這個函數進行回調,所以理論上來說並不需要進行填寫)。

方法parse就是為了解析訪問url後所返回數據的一個方法。

通過chrome打開網址,並打開"Developer Tools"之後,我們可以看到所有的圖片的代碼都如下所示:

所有的圖片都放在了列表裡面(如果你不明白我再說什麼,你應該看看html前端頁面的一些知識,html中ul是無序列表,每一項使用li標籤包圍。遍查整個知乎,爬蟲的居然沒有人詳細的介紹一下chrome的開發者工具的使用方法的,難道工具的使用都不是重點么,我倒是覺得chrome的開發者工具用好了,寫爬蟲的時候才會事半功倍。)

好了,接下來拿取我們數據吧。

parse方法內容如下:

def parse(self, response):
# 如果沒有緩存,保存緩存
if not os.path.exists(os.path.join(os.getcwd(), "meitulu/target.html")):
with open(os.path.join(os.getcwd(), "meitulu/target.html"), wb) as f:
f.write(response.body)

# 提取圖片所在區域,因為只是教程,只選取前兩個圖片的信息
imgul = response.xpath("//ul[@class=img]/li[position()<3]")

# 進一步提取出相應的信息
for item in imgul:
yield {
# 圖片url
"imgurl": item.xpath("./a/img/@src").extract_first(),
# 點攢數
"upvote": item.xpath("./p[1]/span/text()").extract_first(),
# "num": item.xpath("./p[1]/string(.)[2]").extract_first(),
# 瀏覽數
"num": item.xpath("./p[1]/text()").extract_first(),
# 組織名稱
"organization_name": item.xpath(".//p[2]/a/text()").extract_first(),
# 組織url
"organization_url": item.xpath(".//p[2]/a/@href").extract_first(),
# 模特名稱
"model_name": item.xpath("./p[3]/text()").extract_first(),
# 整體標籤名稱
"tag_name": item.xpath("./p[4]//a/text()").extract(),
# 標籤url
"tag_url": item.xpath("./p[4]//a/@href").extract(),
# 主題
"title": item.xpath("./p[5]/a/text()").extract_first(),
}

每一句的內容就是上面注釋所描寫的內容。

好了整體的mtl.py都寫好了(整體代碼寫在了最後。),接下來該運行程序了,scrapy該怎麼運行呢?

還記得之前的cmd框嗎?、對,就是那個,在裡面輸入以下命令就可以運行scrapy了。

scrapy crawl mtl -o mtl.jl

其中mtl就是我們在mtl.py中定義的name,如果你的name不一樣,進行更改就可以了,-o mtl.jl是保留日誌,馬上你就會知道是什麼意思了。

什麼?你把cmd框關了,沒關係,打開cmd框,進入scrapy目錄,還是運行上面的命令就可以了。

什麼?你說你運行不爽,只想用IDE運行?我只能說你想的真多,但是還真的能使用IDE進行運行。只不過方法與上面的有些不同。

在scrapy的目錄下(和scrapy.cfg同一級目錄),新建一個py文件,叫什麼無所謂,然後輸入以下代碼:

from scrapy import cmdline

# 美圖錄圖片下載
cmdline.execute("scrapy crawl mtl -o mtl.jl".split())

運行這個文件就可以了。

好了直接運行這個文件,結果如下:

可以看到,信息已經取出來了。

同時,在scrapy的工程目錄下,生成了一個mtl.jl文件,打開看可以看到將信息存入了進去:

圖上的並不是亂碼,是因為將中文顯示為了utf8編碼顯示(如果我說錯了,會在改正)。

注意:mtl.jl不是覆蓋式寫入是追加式寫入,每運行一次程序mtl.jl體積就會增長,你完全可以刪除mtl.jl再運行程序,程序會重新生成這個文件,或者取消之前文件中的"-o mtl.jl"。(我這種潔癖總是會在這種方面注意-_-|||)

同時,你也將看到有緩存網頁target.html生成。

最終結構如下所示:

這個entry_meitulu.py就是我要運行的入口函數。

好了,同學們,今天這一講就講到這裡,下課,回家。

(如果你仔細的話就會發現,為什麼圖片外面的鏈接地址沒有爬取下來呢?恭喜你,你已經會搶答了。這就是下一講的內容,通過頁面鏈接再爬取其他頁面,其中就會包含了allow_domins的坑。)


推薦閱讀:
相关文章