郭銀芳 韓凱 郭峰明等
關(guān)鍵詞:聚焦爬蟲;搜索策略;scrapy框架;全站爬取;分布式爬取
中圖法分類號:TP39.3 文獻標識碼:A
1引言
假設(shè)有一個需求——需要得到一個電影介紹網(wǎng)站上的所有電影信息。由于不可能通過手動方式獲取大量的數(shù)據(jù),因此需要通過分析網(wǎng)頁、編寫程序進行網(wǎng)頁數(shù)據(jù)的抓取?;ヂ?lián)網(wǎng)信息多種多樣,如果能夠及時了解職位的需求信息,就可以明確學習方向,就業(yè)率就會提高。本文以拉勾網(wǎng)為研究對象,對職業(yè)信息數(shù)據(jù)進行爬取并以可視化的結(jié)論說明就業(yè)需求。
2爬蟲的原理及其技術(shù)研究
2.1網(wǎng)絡爬蟲的原理
網(wǎng)絡爬蟲主要有兩種:一般爬蟲和聚焦爬蟲。一個完整的爬蟲一般包含如下三個模塊:網(wǎng)絡請求模塊、爬取流程控制模塊、內(nèi)容分析提取模塊。對于聚焦爬蟲來說,這一過程所得到的分析結(jié)果還可能對以后的抓取過程給出反饋和指導。相對于通用網(wǎng)絡爬蟲,聚焦爬蟲必須解決三個問題:對抓取目標的描述或定義、對網(wǎng)頁或數(shù)據(jù)的分析與過濾、對URL的搜索策略。
2.2網(wǎng)絡爬蟲技術(shù)的分析
2.2.1發(fā)送請求
確定要爬取的網(wǎng)頁,然后發(fā)送請求,就會得到相應回應,其核心的幾個要素是:請求header和內(nèi)容,響應header和內(nèi)容,url。爬蟲首先需要一個初始的url(也可以說是一個網(wǎng)頁),將網(wǎng)頁的內(nèi)容爬取后,如果要繼續(xù)爬取,則需要解析里面的鏈接。如同一棵樹形的結(jié)構(gòu),以初始url為根節(jié)點,其中每一個網(wǎng)頁又是一個節(jié)點。
在Scrapy中,需要在start_url中寫入待發(fā)送請求的url:https://www.lagou.com/wn/jobs?px=new&pn=1&kd=Java,并且使用瀏覽器的網(wǎng)頁抓包工具,在服務器的響應header中進行查找,以此確定是否有要獲取的信息。
2.2.2 Http請求
一個請求頭中包含很多信息——以簡單爬取為例,只需要寫上User?Agent。以下是瀏覽器請求頭的一部分,“User?Agent”:"Mozilla/5.0(WindowsNT6.1;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/90.0.4430.93Safari/537.36。"2.2.3 Cookie
一般在用戶登錄或者進行某些操作后,服務端會在返回包中列出Cookie信息要求瀏覽器設(shè)置Cookie。如果沒有Cookie,會很容易被辨別出來是偽造請求;由于基于該網(wǎng)站不需要登錄操作也可以獲取到需要的信息,可以不進行登錄操作。
2.2.4 JavaScript加密操作
2.2.5流程控制
所謂爬取流程,就是按照什么樣的規(guī)則順序去爬取。在爬取任務量不大的情況下,爬取的流程控制不會太繁瑣,很多爬取框架都事先幫用戶完成了上述步驟,如Scrapy,只需要自己輸入解析代碼。
在拉勾網(wǎng)中也有很多ajax技術(shù),由于不是主要信息,在此不做分析。本文主要對html文檔本身的信息進行抓取,如Html文檔本身包含內(nèi)容、JavaScript代碼加載內(nèi)容。
處理動態(tài)網(wǎng)頁可以使用selenium模塊,使用該模塊可以得到一個瀏覽器對象,該對象會打開瀏覽器,并且可以得到網(wǎng)頁的全部源碼,而且對于處理ifram之類的動態(tài)模塊也可以簡單的切換串口來實現(xiàn)。
2.3 Scrapy概述
Scrapy使用了純python語言,實現(xiàn)了爬取網(wǎng)頁數(shù)據(jù)、解析數(shù)據(jù)、持久化存儲,為網(wǎng)絡爬蟲提供了非常便捷的模板。在請求網(wǎng)頁方面,也有類似于request或者urllib中的getpost請求。其中,網(wǎng)頁分析工具有etree對象中的xpath方法,而且比etree更加方便——可以在得到一個網(wǎng)頁的源碼之后,直接.xpath使用xpath表達式進行定位。在持久化存儲方面,使用管道存儲會更加方便??偟膩碚f,此框架繼承了多個模塊,使得爬蟲程序更加高效、方便。
2.4 Scrapy框架爬蟲系統(tǒng)的實現(xiàn)
首先創(chuàng)建一個工程,進入工程目錄后,再創(chuàng)建一個爬蟲文件,然后在爬蟲文件中編寫想爬取的起始網(wǎng)頁。由于一般的網(wǎng)站都會搭載UA檢測的反爬檢測程序,所以基本上每個爬蟲都應該進行爬蟲偽裝。
在新建的爬蟲文件中,我們會發(fā)現(xiàn)該文件屬于爬蟲類,它繼承了Scrapy的spider類,在類中可以增加相應的屬性。然后,在爬蟲文件的parse方法中,可以進行解析數(shù)據(jù)等相關(guān)操作以及使用xpath表達式。
在完成數(shù)據(jù)解析后,可以獲得想要的數(shù)據(jù),此時要進行持久化存儲。同時,需要用到工程中的item對象,在item對象中寫入對應的屬性,然后在parse中把數(shù)據(jù)包裝為item對象,然后通過yield關(guān)鍵字進行提交,提交的數(shù)據(jù)會到達Scrapy中的管道類,最后在管道類中進行存儲。
3 基于拉勾網(wǎng)的Scrapy爬蟲實現(xiàn)的具體操作
3.1 拉勾網(wǎng)的網(wǎng)頁分析
首先,對起始url進行分析。通過瀏覽器對起始url進行訪問之后,可以利用瀏覽器抓包工具中的網(wǎng)絡模塊對網(wǎng)頁返回的源碼進行檢查——觀察是否有想要的數(shù)據(jù)。而通過搜索,可以發(fā)現(xiàn)在網(wǎng)頁源碼中有需要的標題、工資及學歷要求。
因為是進行全站爬取,所以需要找到所有頁面的url。通過在網(wǎng)頁源碼中進行尋找,可以發(fā)現(xiàn)url是隱藏的,由于不能在網(wǎng)頁中得到它,所以無法使用crawlspider進行爬取,此時可以使用spider進行直接爬取。為了得到網(wǎng)頁的所有url,通過分析可以發(fā)現(xiàn),每頁只有一個參數(shù)pn不同,因此可以設(shè)置一個記錄page的變量。通過format可以得到所有的url,然后在parse中進行遞歸實現(xiàn)。而在start_url中,放入同一層級的url就可以得到所有的url。
url的結(jié)構(gòu)都大致相同,所以可以使用同一個parse方法。
3.2具體代碼實現(xiàn)
要爬取拉勾網(wǎng)中的職位、工資和學歷要求,可以在pycharm中創(chuàng)建爬蟲工程,然后在爬蟲文件中進行以下主要代碼的編寫。
文件:lg.py
importscrapy
from lgPro.items import LgproItem
classLgSpider(scrapy.Spider):
name='lg'
allowed_domains=['www.xxx.com']
start_urls=['https://www.lagou.com/wn/jobs?
px=new&pn=1&kd=Java']
url='https://www.lagou.com/wn/jobs?px=
new&pn=%d&kd=Java'
page_Num=2
def__init__(self):
foriinrange(1,31):
self.start_urls.append(format(self.url%self.page_
Num))
defparse(self,response):
div_list=response.xpath('/html/body/div/div
[1]/div/div[2]/div[3]/div/div[1]/div')
fordivindiv_list:
title=div.xpath('./div[1]/div[1]/div[1]/a/
text()').extract_first()
salary=div.xpath('./div[1]/div[1]/div[2]//
text()').extract()
salary="".join(salary)
salary_and=salary.split('/')
salary=salary_and[0]
edu=salary_and[1]
print(title,salary)
item=LgproItem()
item["title"]=title
item["salary"]=salary
item["edu"]=edu
yielditem
在lg.py中進行請求和解析操作后,可以將得到
的數(shù)據(jù)提交到管道中。
在items,py中:
importscrapy
classLgproItem(scrapy.Item):
#definethefieldsforyouritemherelike:
title=scrapy.Field()
salary=scrapy.Field()
edu=scrapy.Field()
Pipeline:
fromopenpyxlimportWorkbook
最后,得到爬取結(jié)果——數(shù)據(jù)見圖1。
3.3數(shù)據(jù)可視化
使用百度智能云提供的工具,可以對數(shù)據(jù)進行可視化操作——結(jié)果見圖2。
3.4優(yōu)化
如涉及大規(guī)模的抓取,需要有良好的爬蟲設(shè)計。一般而言,很多開源的爬蟲框架都有限制,因為中間涉及很多其他問題——數(shù)據(jù)結(jié)構(gòu)、重復抓取過濾等。當然,最重要的是要把帶寬利用滿。
如果對一個較大的網(wǎng)站進行爬取,只用一臺機器的效率非常低。此時,可以創(chuàng)建一個分布式機群,據(jù)此對這一組資源進行分布聯(lián)合爬取。同時,需要安裝scrapy?redis組件(這是一個被嵌入在Scrapy框架中的數(shù)據(jù)庫)。此外,使用scrapy?redis可以給原生的scrapy框架提供被共享的管道和調(diào)度器。如果調(diào)度器和管道都是共享的,那么就可以實現(xiàn)多臺機器對同一個資源的爬取,并且能夠統(tǒng)一存儲。
所以,分布式抓取很重要。分布式抓取最重要的就是多臺機器不同線程的調(diào)度和配合,通常會共享一個url隊列,這個隊列可以在每臺機器上進行拋出。
4結(jié)語
從以上分析數(shù)據(jù)來看:對于Java方面的職業(yè)需求,開發(fā)工程師占很大的比例,架構(gòu)師和技術(shù)主管則占很小的比例。
將爬取的數(shù)據(jù)進行可視化操作后,可以得到更加直觀的信息。而且數(shù)據(jù)量越大,數(shù)據(jù)就越精確。但在爬蟲的過程中,或許會遇到三個問題:交互問題,有些網(wǎng)頁會判斷發(fā)出請求是一個程序還是一個正常的用戶,由于添加了驗證碼(滑動滑塊之類的驗證),爬蟲程序遇到這種情況會比較難以處理;ip限制,有的網(wǎng)站會對請求頻率進行檢測,如果程序請求頻率過高,超過了服務器對某個ip的訪問次數(shù)限制,那么可能會對ip地址進行封禁,這也是一種反爬機制。后臺在進行爬取時,由于機器和ip有限,很容易達到上限而導致請求被拒絕。目前,主要的應對方案是使用代理,這樣一來ip的數(shù)量就會多一些,但代理ip依然有限;在網(wǎng)頁源代碼中,難以獲得更詳細的網(wǎng)頁url,如果想進一步提取到每個職位的詳情信息,需要繼續(xù)分析。
總之,按照Scrapy的爬蟲流程、基于網(wǎng)頁的分析,我們得到了想要的數(shù)據(jù),證明基于拉勾網(wǎng)的爬蟲是可以實現(xiàn)的,而且使用的代碼并不算多;基于數(shù)據(jù)進行分析,我們得出了就業(yè)方面的需求。但就出現(xiàn)的問題,仍需繼續(xù)研究、探討。
作者簡介:
郭銀芳(1976—),碩士,副教授,研究方向:數(shù)據(jù)挖掘。