使用python爬蟲工具Scrapy統計簡書文章閱讀量
突然發現多年來一直斷斷續續在學習使用的python,擁有著廣泛的使用場景,從開源硬件、服務器運維、自動化測試,到數學計算,人工智能,都有python的一席之地,在各個領域python有豐富的框架和工具。
聽聞python的Scrapy爬蟲已久,最近正好想對去年一年在簡書寫作的文章做一下統計。作為軟件工程師,肯定不能去按計算器,正好找到一個可以使用scrapy的場景,直接用爬蟲來抓取簡書頁面,然后提取數據作統計。
工作原理和步驟
-
分析要抓取的頁面結構,找到有價值的信息;
-
通過發起http請求,獲得要抓取頁面的html正文;
-
分析html頁面的標簽結構,根據xml層級結構或者css選擇器語法,讀取到需要的document元素;
-
設計數據結構和計算規則,進行統計,然后將結果輸出
抓取網頁的話使用urllib庫其實就可以完成,css選擇器的話,python也有pyquery提供類似jquery的功能。剩下就是簡單的數據統計了。
使用Scrapy動手操作
完整的項目還沒有整理好,暫時不提供代碼,本身核心業務邏輯的代碼量并不多。
安裝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
本次應用中使用pip來安裝scrapy,詳細安裝可以參看官網,安裝pip的同時,需要安裝一些linux開發相關的工具。
需要注意的事項有兩點,首先如果是在mac上安裝的話,由于操作系統以來sis這個庫,而scrapy需要更高版本的sis,無法升級,所以可能有坑,筆者直接使用docker搭建的容器進行開發,所以不存在問題;另外一個是pip源,在國內可能下載速度會比較慢,可以使用國內的源或者F墻下載。
import sys
import scrapy
import csv
class MyJianShuSpider(scrapy.Spider):
name = 'my_jisnshu_spider'
page = 1
userid = 'yourid'
base_url = 'http://www.jianshu.com/u/yourid?order_by=shared_at&page='
start_urls = ['http://www.jianshu.com/u/yourid?order_by=shared_at&page=1']
headers = {
"Host": "www.jianshu.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執行器調用,運行scrapy執行器,就會從入口點start_requests開始執行爬蟲的代碼;使用過javascript的es2015應該會比較容易理解yield,感覺是js也借鑒了很多python的理念。
在Spider執行過程中,任何時候都可以通過調用 scrapy.Request 來發起一個爬蟲抓取操作,callback參數是抓取的網絡請求成功之后的回調函數,url是請求的鏈接地址,headers是http協議的頭部,可以根據需要設置。
簡書頁面的相關結構
查看簡書列表頁面的document結構,很容易找到 #list-container 下面的ul列表就是包含我們要統計的信息的節點,因此可以直接使用scrapy提供的css選擇器來獲取。執行回調函數 response.css('ul.note-list li') 就獲取到了一個列表,對列表做循環處理,取出每一個需要的元素。
#發表時間
publishTimeText = item.css('.author .name > .time ::attr(data-shared-at)').extract_first()
# 摘要
abstractText = item.css('p.abstract ::text').extract_first()
# 文章標題
titleText = item.css('a.title ::text').extract_first()
# 文章的鏈接
articleLink = item.css('a.title ::attr(href)').extract_first()
#統計信息
metaList = item.css('.meta > a ::text').re(r' ([0-9]*)\n')
最后的metaList返回的是一個數組,下標0-2分別是閱讀、評論和點贊的數目。
在實際獲取到的列表頁面中,頁面的文章是通過異步加載,每次獲取一頁數據的,所以在抓取過程中,需要多次抓取每次抓取一頁,直到沒有更多文章為止。
簡書實際上提供了分頁的文章列表頁,可以分頁獲取數據,頁面中頁可以找到是否還有更多文章的標記。為了不破壞讀者探索的樂趣,文章里就不詳細介紹了。
來自:https://segmentfault.com/a/1190000008458083