突然發(fā)現(xiàn)多年來一直斷斷續(xù)續(xù)在學(xué)習(xí)使用的python果覆,擁有著廣泛的使用場景,從開源硬件殖熟、服務(wù)器運維局待、自動化測試,到數(shù)學(xué)計算,人工智能钳榨,都有python的一席之地舰罚,在各個領(lǐng)域python有豐富的框架和工具。
聽聞python的Scrapy爬蟲已久薛耻,最近正好想對去年一年在簡書寫作的文章做一下統(tǒng)計营罢。作為軟件工程師,肯定不能去按計算器饼齿,正好找到一個可以使用scrapy的場景饲漾,直接用爬蟲來抓取簡書頁面,然后提取數(shù)據(jù)作統(tǒng)計缕溉。
工作原理和步驟
- 分析要抓取的頁面結(jié)構(gòu)考传,找到有價值的信息;
- 通過發(fā)起http請求证鸥,獲得要抓取頁面的html正文僚楞;
- 分析html頁面的標(biāo)簽結(jié)構(gòu),根據(jù)xml層級結(jié)構(gòu)或者css選擇器語法枉层,讀取到需要的document元素泉褐;
- 設(shè)計數(shù)據(jù)結(jié)構(gòu)和計算規(guī)則,進行統(tǒng)計鸟蜡,然后將結(jié)果輸出
抓取網(wǎng)頁的話使用urllib庫其實就可以完成膜赃,css選擇器的話,python也有pyquery提供類似jquery的功能揉忘。剩下就是簡單的數(shù)據(jù)統(tǒng)計了财剖。
使用Scrapy動手操作
完整的項目還沒有整理好,暫時不提供代碼癌淮,本身核心業(yè)務(wù)邏輯的代碼量并不多。
安裝python和scrapy
#安裝pip
apt-get install -y build-essential libffi-dev libxml2-dev libxslt1-dev libevent-dev libssl-dev zlib1g-dev python-dev python-pip
pip install -U pip
#安裝scrapy
pip install scrapy
本次應(yīng)用中使用pip來安裝scrapy沦补,詳細(xì)安裝可以參看官網(wǎng)乳蓄,安裝pip的同時,需要安裝一些linux開發(fā)相關(guān)的工具夕膀。
需要注意的事項有兩點虚倒,首先如果是在mac上安裝的話,由于操作系統(tǒng)以來sis這個庫产舞,而scrapy需要更高版本的sis魂奥,無法升級,所以可能有坑易猫,筆者直接使用docker搭建的容器進行開發(fā)耻煤,所以不存在問題;另外一個是pip源,在國內(nèi)可能下載速度會比較慢哈蝇,可以使用國內(nèi)的源或者翻墻下載棺妓。
import sys
import scrapy
import csv
class MyJianShuSpider(scrapy.Spider):
name = 'my_jisnshu_spider'
page = 1
userid = 'yourid'
base_url = 'http://www.reibang.com/u/yourid?order_by=shared_at&page='
start_urls = ['http://www.reibang.com/u/yourid?order_by=shared_at&page=1']
headers = {
"Host": "www.reibang.com",
"User-Agent": "your agent",
"Accept": "*/*"
}
def start_requests(self):
url = self.base_url + str(self.page)
yield scrapy.Request(url, headers=self.headers, callback=self.parse)
def parse(self, response):
for item in response.css('ul.note-list li'):
print publishTimeText = item.css('.author .name > .time ::attr(data-shared-at)').extract_first()
Scrapy基本工作原理
scrapy提供了Spider
類,該類通過start_requests
接口被scrapy執(zhí)行器調(diào)用炮赦,運行scrapy執(zhí)行器怜跑,就會從入口點start_requests開始執(zhí)行爬蟲的代碼;使用過javascript的es2015應(yīng)該會比較容易理解yield吠勘,感覺是js也借鑒了很多python的理念性芬。
在Spider執(zhí)行過程中,任何時候都可以通過調(diào)用scrapy.Request
來發(fā)起一個爬蟲抓取操作剧防,callback參數(shù)是抓取的網(wǎng)絡(luò)請求成功之后的回調(diào)函數(shù)植锉,url是請求的鏈接地址,headers是http協(xié)議的頭部诵姜,可以根據(jù)需要設(shè)置汽煮。
簡書頁面的相關(guān)結(jié)構(gòu)
查看簡書列表頁面的document結(jié)構(gòu),很容易找到#list-container
下面的ul列表就是包含我們要統(tǒng)計的信息的節(jié)點棚唆,因此可以直接使用scrapy提供的css選擇器來獲取暇赤。執(zhí)行回調(diào)函數(shù)response.css('ul.note-list li')
就獲取到了一個列表,對列表做循環(huán)處理宵凌,取出每一個需要的元素鞋囊。
#發(fā)表時間
publishTimeText = item.css('.author .name > .time ::attr(data-shared-at)').extract_first()
# 摘要
abstractText = item.css('p.abstract ::text').extract_first()
# 文章標(biāo)題
titleText = item.css('a.title ::text').extract_first()
# 文章的鏈接
articleLink = item.css('a.title ::attr(href)').extract_first()
#統(tǒng)計信息
metaList = item.css('.meta > a ::text').re(r' ([0-9]*)\n')
最后的metaList返回的是一個數(shù)組,下標(biāo)0-2分別是閱讀瞎惫、評論和點贊的數(shù)目溜腐。
在實際獲取到的列表頁面中,頁面的文章是通過異步加載瓜喇,每次獲取一頁數(shù)據(jù)的挺益,所以在抓取過程中,需要多次抓取每次抓取一頁乘寒,直到?jīng)]有更多文章為止望众。
簡書實際上提供了分頁的文章列表頁,可以分頁獲取數(shù)據(jù)伞辛,頁面中頁可以找到是否還有更多文章的標(biāo)記烂翰。為了不破壞讀者探索的樂趣,文章里就不詳細(xì)介紹了蚤氏。