閱讀459 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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

  上一篇:go 不寫代碼也可以駕馭阿裏雲OpenAPI
  下一篇:go 95187打不通