什么是爬蟲校镐?
網(wǎng)絡(luò)爬蟲
也叫網(wǎng)絡(luò)蜘蛛
衣厘,如果把互聯(lián)網(wǎng)比喻成一個(gè)蜘蛛網(wǎng)垦细,那么蜘蛛就是在網(wǎng)上爬來爬去的蜘蛛择镇,爬蟲程序通過請(qǐng)求url地址,根據(jù)響應(yīng)的內(nèi)容進(jìn)行解析采集數(shù)據(jù)括改,
比如:如果響應(yīng)內(nèi)容是html沐鼠,分析dom結(jié)構(gòu),進(jìn)行dom解析叹谁、或者正則匹配,如果響應(yīng)內(nèi)容是xml/json數(shù)據(jù)乘盖,就可以轉(zhuǎn)數(shù)據(jù)對(duì)象焰檩,然后對(duì)數(shù)據(jù)進(jìn)行解析。
有什么作用订框?
通過有效的爬蟲手段批量采集數(shù)據(jù)析苫,可以降低人工成本,提高有效數(shù)據(jù)量穿扳,給予運(yùn)營(yíng)/銷售的數(shù)據(jù)支撐衩侥,加快產(chǎn)品發(fā)展。
業(yè)界的情況
目前互聯(lián)網(wǎng)產(chǎn)品競(jìng)爭(zhēng)激烈矛物,業(yè)界大部分都會(huì)使用爬蟲技術(shù)對(duì)競(jìng)品產(chǎn)品的數(shù)據(jù)進(jìn)行挖掘茫死、采集、大數(shù)據(jù)分析履羞,這是必備手段峦萎,并且很多公司都設(shè)立了爬蟲工程師
的崗位
合法性
爬蟲是利用程序進(jìn)行批量爬取網(wǎng)頁(yè)上的公開信息,也就是前端顯示的數(shù)據(jù)信息忆首。因?yàn)樾畔⑹峭耆_的爱榔,所以是合法的。其實(shí)就像瀏覽器一樣糙及,瀏覽器解析響應(yīng)內(nèi)容并渲染為頁(yè)面详幽,而爬蟲解析響應(yīng)內(nèi)容采集想要的數(shù)據(jù)進(jìn)行存儲(chǔ)。
反爬蟲
爬蟲很難完全的制止浸锨,道高一尺魔高一丈唇聘,這是一場(chǎng)沒有硝煙的戰(zhàn)爭(zhēng),碼農(nóng)VS碼農(nóng)
反爬蟲一些手段:
- 合法檢測(cè):請(qǐng)求校驗(yàn)(useragent柱搜,referer雳灾,接口加簽名,等)
- 小黑屋:IP/用戶限制請(qǐng)求頻率冯凹,或者直接攔截
- 投毒:反爬蟲高境界可以不用攔截谎亩,攔截是一時(shí)的炒嘲,投毒返回虛假數(shù)據(jù),可以誤導(dǎo)競(jìng)品決策
- ... ...
爬蟲基本套路
- 基本流程
- 目標(biāo)數(shù)據(jù)
- 來源地址
- 結(jié)構(gòu)分析
- 實(shí)現(xiàn)構(gòu)思
- 操刀編碼
- 基本手段
- 破解請(qǐng)求限制
- 請(qǐng)求頭設(shè)置匈庭,如:useragant為有效客戶端
- 控制請(qǐng)求頻率(根據(jù)實(shí)際情景)
- IP代理
- 簽名/加密參數(shù)從html/cookie/js分析
- 破解登錄授權(quán)
- 請(qǐng)求帶上用戶cookie信息
- 破解驗(yàn)證碼
- 簡(jiǎn)單的驗(yàn)證碼可以使用識(shí)圖讀驗(yàn)證碼第三方庫(kù)
- 破解請(qǐng)求限制
- 解析數(shù)據(jù)
- HTML Dom解析
- 正則匹配夫凸,通過的正則表達(dá)式來匹配想要爬取的數(shù)據(jù),如:有些數(shù)據(jù)不是在html 標(biāo)簽里阱持,而是在html的script 標(biāo)簽的js變量中
- 使用第三方庫(kù)解析html dom夭拌,比較喜歡類jquery的庫(kù)
- 數(shù)據(jù)字符串
- 正則匹配(根據(jù)情景使用)
- 轉(zhuǎn) JSON/XML 對(duì)象進(jìn)行解析
- HTML Dom解析
python爬蟲
- python寫爬蟲的優(yōu)勢(shì)
- python語(yǔ)法易學(xué),容易上手
- 社區(qū)活躍衷咽,實(shí)現(xiàn)方案多可參考
- 各種功能包豐富
- 少量代碼即可完成強(qiáng)大功能
- 涉及模塊包
- 請(qǐng)求
urllib
urllib2
cookielib
- 多線程
threading
- 正則
re
- json解析
json
- html dom解析
pyquery
beautiful soup
- 操作瀏覽器
selenium
- 請(qǐng)求
實(shí)例解析
斗魚主播排行
- 目標(biāo)數(shù)據(jù)
- 獲取排行榜主播信息
- 來源地址
- [排行榜地址]
-
[主播房間地址]
-
https://www.douyu.com/xxx
- xxx=房間號(hào)
-
https://www.douyu.com/xxx
- 結(jié)構(gòu)分析
- 通過抓包 [排行榜地址]鸽扁,[主播房間地址] (谷歌調(diào)試network/charles/fiddler)
- 獲得排行數(shù)據(jù)接口:https://www.douyu.com/directory/rank_list/game
- 參數(shù)確認(rèn)(去掉不必要參數(shù))
- cookie確認(rèn)(去掉不必要cookie)
- 模擬請(qǐng)求(charles/fiddler/postman)
- 獲得主播房間信息數(shù)據(jù)
- 發(fā)現(xiàn)$ROOM是主播房間信息,在頁(yè)面的script標(biāo)簽的js變量中镶骗,可使用正則工具寫表達(dá)式去匹配
- 獲得排行數(shù)據(jù)接口:https://www.douyu.com/directory/rank_list/game
- 通過抓包 [排行榜地址]鸽扁,[主播房間地址] (谷歌調(diào)試network/charles/fiddler)
- 實(shí)現(xiàn)構(gòu)思
- 通過請(qǐng)求 [主播排行接口] 獲取 [排行榜數(shù)據(jù)]
- [排行榜數(shù)據(jù)] 中有主播房間號(hào)桶现,可以通過拼接獲得 [主播房間地址]
- 請(qǐng)求 [主播房間地址] 可以獲得 [$ROOM信息] ,解析可以獲得主播房間信息
- 操刀編碼
申明:此例子僅作為爬蟲學(xué)習(xí)DEMO鼎姊,并無其他利用
基于python實(shí)現(xiàn)爬蟲學(xué)習(xí)基礎(chǔ)demo
def douyu_rank(rankName, statType):
'''
斗魚主播排行數(shù)據(jù)抓取
[數(shù)據(jù)地址](https://www.douyu.com/directory/rank_list/game)
* `rankName` anchor(巨星主播榜),fans(主播粉絲榜),haoyou(土豪實(shí)力榜),user(主播壕友榜)
* `statType` day(日),week(周),month(月)
'''
if not isinstance(rankName, ERankName):
raise Exception("rankName 類型錯(cuò)誤骡和,必須是ERankName枚舉")
if not isinstance(statType, EStatType):
raise Exception("statType 類型錯(cuò)誤,必須是EStatType枚舉")
rankName = '%sListData' % rankName.name
statType = '%sListData' % statType.name
# 請(qǐng)求獲取html源碼
rs = rq.get(
"https://www.douyu.com/directory/rank_list/game",
headers={'User-Agent': 'Mozilla/5.0'})
# 正則解析出數(shù)據(jù)
mt = re.search(r'rankListData\s+?=(.*?);', rs, re.S)
if (not mt):
print u"無法解析rankListData數(shù)據(jù)"
return
grps = mt.groups()
# 數(shù)據(jù)轉(zhuǎn)json
rankListDataStr = grps[0]
rankListData = json.loads(rankListDataStr)
dayList = rankListData[rankName][statType]
# 修改排序
dayList.sort(key=lambda k: (k.get('id', 0)), reverse=False)
return dayList
def douyu_room(romm_id):
'''
主播房間信息解析
[數(shù)據(jù)地址](https://www.douyu.com/xxx)
'romm_id' 主播房號(hào)
'''
rs = rq.get(
("https://www.douyu.com/%s" % romm_id),
headers={'User-Agent': 'Mozilla/5.0'})
mt = re.search(r'\$ROOM\s+?=\s+?({.*?});', rs, re.S)
if (not mt):
print u"無法解析ROOM數(shù)據(jù)"
return
grps = mt.groups()
roomDataStr = grps[0]
roomData = json.loads(roomDataStr)
return roomData
def run():
'''
測(cè)試爬蟲
'''
datas = douyu_rank(ERankName.anchor, EStatType.month)
print '\r\n主播排行榜:'
for item in datas:
room_id = item['room_id']
roomData = douyu_room(room_id)
rommName = None
if roomData is not None:
rommName = roomData['room_name']
roomInfo = (u'房間(%s):%s' % (item['room_id'], rommName))
print item['id'], item[
'nickname'], roomInfo, '[' + item['catagory'] + ']'
run()
運(yùn)行結(jié)果:
主播排行榜:
無法解析ROOM數(shù)據(jù)
1 馮提莫 房間(71017):None [英雄聯(lián)盟]
2 阿冷aleng丶 房間(2371789):又是我最喜歡的阿冷ktv時(shí)間~ [英雄聯(lián)盟]
3 勝哥002 房間(414818):勝哥:南通的雨下的我好心累相寇。 [DNF]
4 White55開解說 房間(138286):盧本偉五五開 每天都要很強(qiáng) [英雄聯(lián)盟]
5 東北大鵪鶉 房間(96291):東北大鵪鶉 宇宙第一寒冰 相聲藝術(shù)家慰于! [英雄聯(lián)盟]
6 老實(shí)敦厚的笑笑 房間(154537):德云色 給兄弟們賠個(gè)不是 [英雄聯(lián)盟]
7 劉飛兒faye 房間(265438):劉飛兒 月底吃雞 大吉大利 [絕地求生]
8 pigff 房間(24422):【PIGFF】借基地直播,沒OW [守望先鋒]
9 云彩上的翅膀 房間(28101):翅:還是抽天空套刺激唤衫! [DNF]
10 yyfyyf 房間(58428):無盡的9月婆赠,殺 [DOTA2]
# 馮提莫 房間做周年主題,解析會(huì)有問題