張安啟 羅批



摘要 新浪微博是數據的重要發源地。為實現數據快速抓取,本文在研究反爬機制的基礎上,設計了基于Scrapy的微博爬蟲,并對各模塊進行了詳細闡述。實驗表明,該爬蟲具有支持關鍵字匹配、速度快、簡單的特點。為研究者提供了快速、準確、方便地獲取微博數據的途徑。
【關鍵詞】Scrapy 爬蟲 微博
微博自誕生之日起就獲得迅猛發展。截至2017年9月,新浪微博的活躍用戶高達3.76億,較之去年同期增長27%。微博作為網民交流互動的平臺,時刻產生著大量的數據,對于研究具有重要意義。當前通過微博開放接口(API)獲取數據存在諸多的限制,而且流程復雜、速度較慢。
Sctapy是為爬取網絡結構性數據而編寫的應用框架,具有簡單、模塊清晰的特點。Scrapy框架對于設計爬取新浪微博數據的爬蟲具有十分重要的意義。本文研究了當前微博的反爬機制,并對該機制制定了相應的策略。并依此設計了基于Scrapy的微博爬蟲。并通過實驗驗證了設計的爬蟲的有效性。
1 當前的反爬蟲機制
當前的反爬機制主要有以下四種:
(1) IP地址的限制。微博服務器對登錄網站的IP地址進行監測,如果某一個IP地址訪問頻率過高或者持續時間過久,就會判定使用該IP的用戶為爬蟲并對該IP進行封鎖。令其無法訪問微博或者通過驗證后方可進行訪問。
(2)瀏覽器的限制。瀏覽器的標識存在于headers屬性當中。如果檢測到某一個瀏覽器頻繁地訪問,便會封殺該瀏覽器。
(3)對賬號的限制。因為一個人不可能頻繁大量長時間地訪問微博,因此如果某一賬號頻繁不間斷的訪問微博,該賬號就需要重新驗證方可繼續訪問。
(4)對訪問頻率的限制。由于爬蟲瀏覽速率非??欤哂谄胀ㄈ藶g覽網頁的幾十倍甚至上百倍。因此,如果訪問頻率過高,也會將其判定為爬蟲,對其要求進行驗證。
由此可見,當前的反爬機制主要是通過對正常網民行為進行識別。當某個網民的行為與正常網民的行為不一致的時候,就會判定該網民為爬蟲。因此,為了應對反爬蟲機制,就應該讓爬蟲行為與正常用戶行為更為相似。
2 應對反爬蟲的策略
針對微博的反爬蟲策略,在此制定防止反爬蟲的設計。
(1)建立由多個IP地址組成的IP池。每進行一次新的頁面訪問,從IP池中隨機抽取一個IP地址。這樣可以避免某個IP地址被封殺。
(2)建立多個移動瀏覽器標識的客戶端類型池。由于當前人們習慣于使用手機等移動設備上網,因而使用移動設備瀏覽器登錄網站理論上講是個較為安全的方式。從移動客戶端類型池中每次隨機抽取一個客戶端,模擬網民登陸。
(3)建立多個賬號組成的賬號池。每次訪問新的頁面,從賬號池中隨機抽取一個賬號,有效降低單個賬號的訪問頻率。
(4)增大訪問時延。通過增大訪問時延,降低訪問頻率,模擬正常人的訪問,實現對反爬蟲機制的回避。
3 基于Scrapy的爬蟲工作原理
圖1是Scrapy框架圖,現在對其各個模塊以及運行流程進行介紹。
3.1 模塊介紹
引擎( Scrapy Engine):它是整個框架的核心,數據在各個模塊的流動都需要通過引擎的牽引來實現。
調度器(Schedule)接受引擎模塊發來的request,并將request壓入隊列。在進行微博抓取的時候主要是URL隊列。調度器對URL隊列進行處理,主要是排序與去重。
下載器(Downloader):從互聯網上獲取數據,并將內容反饋給爬蟲( Spiders)模塊。
管道(Pipelines):處理從網頁中抽取的實體(Items),主要功能是驗證實體有效性和清除無意義的信息。頁面被解析后,將會被發送到管道中進行處理。本實驗結合Mongodb數據庫,通過Pipelines將數據直接導入Mongodb數據庫中。
中間件(Middlewares):處理兩個模塊之間的信息請求以及進行相應。
3.2 運行流程
引擎將調度器里的URL封裝成請求( Requests),傳送到下載器,下載器從互聯網上將數據下載下來,將其封裝成應答包( Responses)并傳送給爬蟲。爬蟲對應答包進行解析得到實體或URL。如果是實體,則交給管道進行進一步處理。如果是URL,則將結果交給調度器處理。
4 爬蟲的各個模塊設計
4.1 Cookies模塊
Cookies模塊主要用于在一定時間內,記錄登錄數據,在進行登錄的時候可以保持登錄的狀態。在本文設計的cookies模塊中,記錄的是多個用戶賬號組成的賬號池,用來登陸微博網站時先切換賬號。主要偽代碼如下:
weib0 =[{num‘:‘1 5022967940,psw:OC3LKP'),……]#建立微博賬號池,賬號池中的賬號越多,被封殺的可能性越低,時延可以設置越低,爬取速度越快
def getCookies(、veibo):#獲取Cookies
cookies =[]
loginURL= 'https:,//weibo.cn/login/'#微博網站登陸界面
for elem in weibo:#從微博賬號池中抽取一個賬號進行登錄
account= elem[num]
password = elem[psw‘]
try:
browser= webdriver.PhantomjS(desiredcapabilities=dcap) browser.get(loginURL)
if出現需要識別的代碼
人工識別代碼并在界面上輸入代碼
4.2 Items模塊
該模塊主要明確抓取數據的類型。本文抓取的實驗數據類型是用戶的用戶名,用戶粉絲數、微博內容、發布時間、轉發數、點贊數以及評論數三個指標。其主要代碼為:
from scrapy import Item, Field
class Informationltem(ltem):#個人信息
id= Field()#用戶ID
Fans= Field()#用戶粉絲
Content= Field()#微博內容
PubTime= Field()#發表時間
Transfer= Field()#轉發數
Like= Field()#點贊數
Comment= Field()#評論數
4.3 Middlewares模塊
該模塊主要實現瀏覽器、IP地址以及登陸賬號(登陸賬號在cookies中)的轉換,防止被禁止爬取數據。其主要代碼如下:
import random
import urlllib.request
from cookies import cookies
agents=["Mozilla/5.0 (Linux; U;Android 2.3.6; en-us; Nexus S Build/GRK39F)AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 Mobile Safari/533.1”,—…]#建立移動瀏覽器池
ips= [23.25.35.66,….]#建立ip地址池
class UserAgentIPMiddleware(object): #更換User-Agent與IP
def process_request(self, request, spider):
agent= random.choice(agents)#從移動瀏覽器池中隨機抽取一個移動瀏覽器
ip= random.choice(ips)#從IP池中隨機抽取IP
request.headers["User-Agent"]= agenr##訪問網站的瀏覽器頭設置為抽取的移動瀏覽器
ip_support=urllib.requestProxyHandler({ thttp':ip})
opener= urllib.request.build_opener(ipsupport)
urllib.request.install_opener(opener)
class CookiesMiddleware(object):#更 換Cookie
def process_request(self, request, spider):
cookie= random.choice(cookies)#從cookies池中隨機抽取cookie
request.cookies= cookie
4.4 Pipelines模塊
該模塊主要對抓取的數據進行解析校對,然后傳入Mongodb數據庫中。其主要代碼如下:
import pymongo
fromltems import Informationltem
class MongoDBPipleline(object):#初始化設置MongoDB數據庫
defjnit_(selt):
clinet= pymongo.MongoClient("localhost",27017)
db = clinet["Sina"]
selflnformation= db["Information"]
def processjtem(selt item, spider):#判斷item的類型,并作相應的處理,再入數據庫
ifisinstance(item, Informationltem):
try:
self.lnformation.insert(dict(item》
except Exception:
pass
retumltem
4.5 Settings模塊
該模塊主要設置抓取的間隔時間與關鍵詞等信息。在這設置抓取間隔為6,關鍵詞為租賃房。主要代碼如下:
DOWNLOAD__ DELAY=6井間隔時間
KEY WORD=‘租賃房#關鍵詞
4.6 Spider主程序(引擎模塊)
該模塊是整個程序的核心,通過該模塊實現數據的抓取。主要代碼如下:
def start_requests(self):#依據關鍵詞獲取微博,并將該微博的用戶的地址url
url={url} ?keyword= {keyword}format(url=self.search_url, keyword=KEYWORD)
# search url為微博搜索界面
defparse (self, response):#抓取微博數據
selector= Selector(response)
rweets=selector.xpath(body/div[@class='c”and@idD
for tweet in tweets:
nveetsltems= Tweetsltem()
id= tweet.xpath(@id').extract_first()#獲取微博ID
fans= response.xpath(”//div[@class=tip2]/a[contains(text(),‘粉絲[)]/text()”)#獲取粉絲
content= tweet.xpath(‘div/span[@class=”ctt”]/text()).extract_first()#獲取微博內容
like= re.findall(u\u8d5e\[(\d+)、],tweet.extract(》#獲取點贊數
transfer= re.findall(u‘\u8f6c\u53d1、[(\d_)m tweet.extracr(》#獲取轉載數
comment= re.findall(u‘\u8bc4\u8bba、[(\d+)m tweet.extract(》#獲取評論數5實驗運行平臺
實驗平臺:聯想E431電腦
具體配置:CPU intel i5-4320、8G內存、2G顯卡、256G固態硬盤
6 實驗分析
本實驗以群眾最為關心的租賃房作為關鍵詞進行數據的抓取,在爬蟲運行的86小時23分鐘內,共計爬取了9910個用戶的18633554條數據。
圖2是爬取的部分數據截圖:從左到右為用戶名、粉絲數、微博內容、轉發數、點贊數、評論數及發布時間。
依據粉絲數多少繪制用戶的累計分布概率進行繪制,得到的結果如圖3所示。
這說明關于“租賃房”這一社會熱點話題的參與者的粉絲呈冪率分布,關心該話題的大部分人為擁有少量粉絲的普通民眾。這也與當前社會現實相一致,擁有大量粉絲的網絡大V占據極少數,絕大多數的網民只擁有極少數的粉絲。
7 總結
通過分析當前的反爬機制,運用Scrapy框架簡單、模塊清晰的特點以及python豐富完善的標準庫,設計了基于Scrapy的網絡爬蟲。通過實驗證實,該爬蟲能夠實現對數據的高效爬取,為科研工作者獲取微博數據提供了一個較為簡單快捷的工具。在搜索時,只需要將關鍵詞修改,就可實現該主題數據的爬取。
參考文獻
[1]新浪微博數據中心:2 017微博用戶發展報告[EB/OL] http://www. useit. com. cn/thread-17562-1-1.html, 2017.
[2]郭濤,黃銘鈞,社區網絡爬蟲的設計與實現[J],智能計算機與應用,2012,2 (04):65-67.
[3]廉捷,周欣,曹偉等.新浪微博數據挖掘方案[J].清華大學學報:自然科學版,2011, 51(10):1300-1305.
[4]趙本本,殷旭東,王偉.基于Scrapy的GitHub數據爬蟲[J],電子技術與軟件工程,2016,6:199-202.
[5]陳利婷,大數據時代的反爬蟲技術[J].電腦與信息技術,2016,24 (06): 60-61.
[6]安子建.基于Scrapy框架的網絡爬蟲實現與數據抓取分析[D].長春:吉林大學,2016.
[7]陳琳,任芳,基于Python的新浪微博數據爬蟲程序設計[J].信息系統工程,2016 (09):97-99.