Python爬蟲實戰
引言
- 網絡爬蟲是抓取互聯網信息的利器,成熟的開源爬蟲框架主要集中於兩種語言Java和Python。主流的開源爬蟲框架包括:
1.分布式爬蟲框架:Nutch
2.Java單機爬蟲框架:Crawler4j, WebMagic, WebCollector、Heritrix
3.python單機爬蟲框架:scrapy、pyspider
- Nutch是專為搜索引擎設計的的分布式開源框架,上手難度高,開發複雜,基本無法滿足快速開發的需要。
- Java單機類爬蟲框架普遍容易上手,最大的優勢是在Java技術的生態圈非常完善,輪子很多,同一個功能的輪子都有好幾個不同的廠家提供,對於搭建完整的係統或者整合到現有的Java係統中都較為容易。
使用python開發的爬蟲框架最大的特點是開發效率非常高,做相同的事情,代碼量要遠少於使用Java開發。缺點也比較明顯,如果對python不熟悉的情況下,代碼調試的時間會耗費掉編碼時省下來的時間,甚至會浪費得更多,在爬取業務非常複雜的情況下,會花掉更多的調試時間。
總結下各個爬蟲框架的特點:
語言 | 插件 | 上手難度 | 支持分布式 | 支持JS頁麵抓取 | 特點 | |
---|---|---|---|---|---|---|
Nutch | Java | 支持,開發複雜 | 高 | 支持 | 不支持 | 專門為搜索引擎設計 |
Crawler4j | Java | 不支持 | 低 | 不支持 | 不支持 | 簡單 |
WebMagic | Java | 支持 | 低 | 不支持 | 不支持 | scrapy的Java版本 |
WebCollector | Java | 支持 | 低 | 不支持 | 支持 | 內置selenium |
Heritrix | Java | 支持 | 低 | 不支持 | 不支持 | 擴展性較好 |
scrapy | Java | 支持 | 低 | 擴展可支持 | 不支持 | 擴展性強 |
pyspider | Java | 支持 | 低 | 支持 | 支持 | 強大的爬蟲管理和監控 |
- 所有的框架都解決了以下幾個問題:
1. URL管理,URL去重
2. 多線程抓取,線程池管理
3. 代理
4. 指定cookie
5. 集成網頁解析器
6. 廣度遍曆或者深度遍曆抓取
- 使用框架的最大好處是上述的問題都已經被解決,減少了開發的成本。缺點是開發模式受限於框架的設計思想,由於對框架的掌控程度有限,深度定製需要修改源碼時會帶來額外的成本。
python爬蟲
- 使用python編寫爬蟲具有非常明顯的優勢,當滿足以下需求時,強烈建議首選python作為開發語言。
1. 減少開發量,並快速的看到結果
2. 垂直領域的精確抓取,具有明確的抓取對象,需要格式化抽取數據
3. 指定ajax請求抓取,或有抓取有限的url請求數據
4. 不作為持續集成的係統,僅需要快速收集數據
basic版爬蟲
- 在進行精確數據抓取時,使用框架並不一定具有優勢。框架提供的主要功能:1.多線程抓取,2.URL管理和去重,3.增量抓取,4.監控。
1. 多線程抓取的作用是提高抓取效率,但是現在主流的搜索平台,在關鍵數據上都做了防抓取的工作,過快的抓取頻率很容易導致當前IP的流量被視為異常流量,最壞的結果是IP被列入網站的黑名單,被限流或禁止訪問一段時間。
2. 在進行精確數據抓取時,URL去重的作用並不大,甚至不需要。
3. 增量抓取是個很實用的功能,對於大規模的數據抓取很有必要,因為在數據抓取的過程中很可能出現異常,或者某些原因需要暫停抓取過程,導致某些數據沒有成功獲取,增量抓取機製能夠很好的支持在特殊情況下的數據抓取延續性。
4. 監控,大型數據抓取係統必不可少的一個功能。
- 很多爬蟲框架並不直接支持增量抓取和監控功能,作為一個小範圍的快速的精確數據抓取的爬蟲,增量抓取和監控並不是必須的。
- basic爬蟲具有的基本功能:
1. 發起http請求
2. html解析
3. json解析
- 隻要實現這三個功能,就能夠寫出一個從搜索平台上抓取數據的爬蟲,在python的世界裏,使用urllib2+BeautifulSoup+simplejson/json就能快速的實現一個爬蟲。
- 發起一個http登錄請求:
import urllib2
import json
header = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36','Content-Type':'application/json'}
data = json.dumps({"userName":"wenbin", "password":"passwd"})
request = urllib2.Request(loginUrl, None, header)
response = urllib2.urlopen(request)
data = response.read()
response.close()
- 有時需要保存cookie,或者攜帶cookie發送請求,將代碼改造一下:
import urllib2
import json
import cookielib
header = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36','Content-Type':'application/json}
loginUrl = "${loginUrl}"
data = json.dumps({"userName":"wenbin", "password":"passwd"})
cookieFileName = 'cookie.txt'
# set cookie to request
cookie = cookielib.MozillaCookieJar(cookieFileName)
handler = urllib2.HTTPCookieProcessor(cookie)
opener = urllib2.build_opener(handler)
request = urllib2.Request(loginUrl, data, header)
response = opener.open(request)
# save the cookie
cookie.save(ignore_discard=True, ignore_expires=True)
response.close()
dataUrl = "${dataUrl}"
request = urllib2.Request(dataUrl, None, header)
data = response.read()
response.close()
- cookie也可以從已有的文件中讀取:
cookie = cookielib.MozillaCookieJar()
# get cookie from file
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
handler = urllib2.HTTPCookieProcessor(cookie)
opener = urllib2.build_opener(handler)
request = urllib2.Request(url, None, header)
response = opener.open(request)
data = response.read()
response.close()
- BeautifulSoup解析html的demo
data = "<html><h2 ><span>100</span></h2><lu><li ><div ><a href="www.demo.com/1/2/3">高大上小區</a></div></li><li ><div ><a href="www.demo.com/1/2/3">高大上小區</a></div></li><li ><div ><a href="www.demo.com/1/2/3">高大上小區</a></div></li></lu></html>"
# load html content
soup = BeautifulSoup(data, "html.parser")
# find the first <h2> with class=total fl
totalCount = soup.find('h2', attrs={'class': 'total fl'}).span.contents[0]
# find all <li> with class=clear xiaoquListItem
xiaoquTag = soup.find_all("li", attrs={'class': 'clear xiaoquListItem'})
pageSize = len(xiaoquTag)
for tag in xiaoquTag:
# find all <div> with class=title belong to tag
titleSet = tag.findAll("div", attrs={'class': 'title'})
for title in titleSet:
xiaoquUrl = title.a['href']
xiaoquId = str(xiaoquUrl).split('/')[4]
xiaoquName = title.a.contents[0]
xiaoquList.append([xiaoquId,xiaoquName,xiaoquUrl])
print xiaoquList
- 在web 2.0的時代,許多數據是通過ajax請求的方式異步獲取的,通常返回的數據為json格式,在許多情況下需要進行json解析, python提供了非常簡單易用的json解析工具:json/simplejson,json和simplejson幾乎是一樣的,但simplejson在python 2.4以上的版本可以用,json在python 2.6以上版本可用
import json
jstr = '{"demoName":"demo","version":1}'
jObject = json.loads(json_string)
print jObject['version']
object={"demoName":"demo","version":1,"cont":[1,2]}
print json.dumps(object)
- 使用urllib2+BeautifulSoup+simplejson/json編寫的簡易爬蟲,能夠實現對垂直類搜索平台的數據精確抓取和數據解析。
爬蟲進階
- basic版爬蟲能夠完成大部分的數據的抓取,但是仍然在一些情況下是無法抓取到目標數據的,比如當對方的數據是通過javascript對接口數據進行複雜的處理之後才輸出的,那麼直接抓取接口就無法獲得正確的數據,而basic版的爬蟲是無法運行javascript腳本的。
- 為了能夠正確運行javascript腳本,獲取異步加載的、經過複雜處理之後才輸出的數據,需要升級basic爬蟲。在python體係下,推薦使用Selenium+PhantomJS+BeautifulSoup的組合實現新的爬蟲。PhantomJS用來解析javascript和頁麵渲染,Selenium用來驅動PhantomJS,BeautifulSoup用來解析渲染結束後的html頁麵。
- 在mac os下,使用PhantomJS發起請求,並使用BeautifulSoup解析渲染完成的html:
from selenium import webdriver
import os
from bs4 import BeautifulSoup
driverDir = "${dirvierDir}"
os.environ["webdriver.phantomjs.driver"] = driverDir
driver = webdriver.PhantomJS(driverDir)
url = '${url}'
driver.get(url)
data = self.driver.page_source
print data
soup = BeautifulSoup(data, "html.parser")
driver.close()
- 其中,chromedriverDir為chrome瀏覽器的內核所在的文件目錄。
- selenium的webdriver還支持chrome、firefox和ie等瀏覽器,使用PhantomJS的原因是PhantomJS沒有UI,因此運行速度更快,消耗的資源更少。進階的爬蟲具有更好的反爬蟲能力,能夠適應更多的場景。
高級爬蟲
- 一個高級的爬蟲,並不僅僅在於實現的技術、設計的理念有多先進,更在於其對被抓取的網站的服務器有多友好。無視服務器壓力的爬蟲一般會定義為低級的爬蟲,把服務器拖垮,即影響了服務提供方的正常運營,也直接導致所需的數據無法獲取。當然,肆無忌憚的爬蟲也很容易被反爬蟲程序發現,然後被封殺,或被‘投毒’。高級的爬蟲需要具備以下幾個特點:
1. 控製對目標網站的抓取速度,如果僅僅是需要收集數據,而不要求數據的非常高的實時性,建議將訪問頻率控製到正常瀏覽的水平。
2. 具有生命周期的管控,數據收集完成後,需要停止爬蟲的工作。
3. 健壯性,需要保證爬蟲程序的健壯性,能夠容忍壞的HTML、奇怪的服務器行為,不會因此而程序中斷。
4. 可擴展性,通用功能組件化,便於複用,也便於修改。
5. 適當的監控,留下關鍵的抓取記錄,便於異常恢複和抓取進度監控。
6. 具有一定的‘反爬蟲’抗性
- 隻要爬蟲存在,‘反爬蟲’就不會消失,做一個有禮貌的爬蟲,將會極大的降低被‘反’的風險。
小結&DEMO
- 使用python能夠非常快速、便捷的編寫數據抓取的爬蟲程序,能夠滿足大部分情況下的數據收集需求,帶來無與倫比的快速反饋體驗
- 做一個有禮貌的爬蟲,為了世界和平,請控製抓取速度
- 真正的爬蟲和反爬蟲之戰是RMB玩家的遊戲,是技術和金錢的較量。
- demo的github地址:https://github.com/huntertan/lstm-spider
最後更新:2017-04-21 11:30:33