貓眼電影—流浪地球爬蟲(1)

再來一波流浪地球的爬蟲莉兰,不過這次爬的是貓眼電影崔挖。而且這次不再是用scrapy而是用最常規(guī)的方法requests矢渊。
同時(shí)這里還要詳細(xì)講幾個(gè)別的問題战转。

  • 什么是Ajax
  • 如何進(jìn)行反爬
  • 如何儲(chǔ)存到MongoDB中

首先,常規(guī)操作進(jìn)行貓眼電影的網(wǎng)址進(jìn)行分析予弧。但是我們發(fā)現(xiàn)在其網(wǎng)頁端刮吧,它的評(píng)論往往沒有那么多。
此時(shí)我們用的是貓眼電影的手機(jī)端url:http://m.maoyan.com/movie/248906/morecomments?_v_=yes

貓眼頁面.png

大家可以往下滑掖蛤,發(fā)現(xiàn)在頁面沒有跳轉(zhuǎn)的情況下杀捻,內(nèi)容就加載出來了,可以知道這里用的是Ajax加載的方式蚓庭。
那么什么是Ajax呢致讥?

Ajax

Ajax,全稱為Asynchronous JavaScript and XML彪置,即異步的JavaScript和XML拄踪。它不是一門編程語言蝇恶,而是利用JavaScript在保證頁面不被刷新拳魁、頁面鏈接不改變的情況下與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁的技術(shù)。

對(duì)于傳統(tǒng)的網(wǎng)頁撮弧,如果想更新其內(nèi)容潘懊,那么必須要刷新整個(gè)頁面姚糊,但有了Ajax,便可以在頁面不被全部刷新的情況下更新其內(nèi)容授舟。在這個(gè)過程中救恨,頁面實(shí)際上是在后臺(tái)與服務(wù)器進(jìn)行了數(shù)據(jù)交互,獲取到數(shù)據(jù)之后释树,再利用JavaScript改變網(wǎng)頁肠槽,這樣網(wǎng)頁內(nèi)容就會(huì)更新了。

Ajax實(shí)現(xiàn)原理

Ajax的原理簡單來說通過XmlHttpRequest對(duì)象來向服務(wù)器發(fā)異步請(qǐng)求奢啥,從服務(wù)器獲得數(shù)據(jù)秸仙,然后用javascript來操作DOM而更新頁面。
具體大家可以自行Google哦桩盲。

Ajax分析方法

那么我們?cè)谒⑿录偶停@取信息的時(shí)候,我們看到的url是沒有變化的赌结,而是一次次的Ajax請(qǐng)求渲染了網(wǎng)頁捞蛋。那么我們應(yīng)該去哪里查看呢?
當(dāng)然是右鍵——檢查柬姚,借助開發(fā)者工具進(jìn)行檢查拟杉。

檢查.png

不過這一次我們關(guān)注的就不是Elements選項(xiàng)卡了,而是Network選項(xiàng)卡量承。
我們進(jìn)行切換并且刷新捣域,就能獲得如圖所示的信息:

Network.png

那么在這里:


XHR.png

選擇XHR,篩選出來的就是Ajax請(qǐng)求啦宴合。
我們選擇開頭有comments.json的條目焕梅,在它的Request Headers可以看到比傳統(tǒng)的請(qǐng)求頭中多了一項(xiàng)X-Requested-With: superagent,而superagent是一種輕量級(jí)的Ajax請(qǐng)求方式卦洽。

隨后贞言,我們點(diǎn)擊Preview選項(xiàng)卡,可以看到網(wǎng)頁是json格式阀蒂,而chrome已經(jīng)幫我們解析出來了

json.png

可以看到在data下该窗,有我們需要的東西。
此時(shí)蚤霞,想要獲取這些內(nèi)容非常容易了酗失,就像是獲取字典的值一樣。

res = requests.get(url,timeout,headers=self.headers)
comments = res.json()['data']['comments']

這樣我們就能獲取評(píng)論數(shù)據(jù)昧绣,進(jìn)行下一步提取了规肴。

同時(shí)我們?cè)?code>Headers里可以看到真實(shí)的url:http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=0&limit=15&ts=0&level=2&type=3,并且請(qǐng)求方式是get
那么我們多點(diǎn)擊幾個(gè)拖刃,觀察url就會(huì)發(fā)現(xiàn)删壮,其中變化的只有參數(shù)offset,并且是每15進(jìn)行累加兑牡。

代碼

直接上代碼吧央碟。

import requests
import time
from datetime import datetime
from pymongo import MongoClient
from lxml import etree
import random


class maoyan():
    def __init__(self):
        self.headers = {
                'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36                       (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
                'cookie':"_lxsdk_cuid=163f4936fa628-0651e9953b7cba-791238-144000-163f4936fa7c8; v=3; iuuid=A83BE960AA7E11E8B6349B995F5768EC558368427A114227869310FFD50B50A1; webp=true; ci=185%2C%E5%98%89%E5%85%B4; _lx_utm=utm_source%3Dgoogle%26utm_medium%3Dorganic; _lxsdk=438345E032A511E9BDC5F9F05A760829F59E3BE1237E422D9B95E24FCA63731A; __mta=254523319.1528816694943.1535432227454.1550402539437.7; _lxsdk_s=168fb2aa1e2-1c1-2d8-2a8%7C%7C24",
                }
    #反爬
    def get_comments(self,i,timeout,proxy=None):
        page = i*15
        num_retries = 6
        url = 'http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset={}&lim                 it=15&ts=1550476464599&level=2&type=3'.format(page)
        
        if proxy == None:
            try:
                res = requests.get(url,timeout,headers=self.headers)
                
            except:
                if num_retries>0:
                    time.sleep(10)
                    print('網(wǎng)頁獲取出錯(cuò),10s后將獲取倒數(shù)第{}次'.format(num_retries))
                    res= requests.get(url,timeout,headers=self.headers)
                    num_retries -= 1
                    
                else:
                    print('開始使用代理')
                    time.sleep(10)
                    proxy = self.get_ip
                    res = requests.get(url,timeout,proxies=proxy,headers=self.headers)
                    
        else:
            try:
                proxy = self.get_ip
                res = requests.get(url,timeout,proxies=proxy,headers=self.headers)
                
            except:
                if num_retries > 0:
                    time.sleep(10)
                    proxy = self.get_ip
                    res = requests.get(url,timeout,proxies=proxy,headers=self.headers)
                else:
                    print('代理失敗均函,取消代理')
                    res = requests.get(url,timeout,headers=self.headers)

        
        comments = res.json()['data']['comments']
        return comments
    #保存到MongoDB中
     def save_data(self,comment):
        client = MongoClient()
        db = client['maoyan']
        collection = db['lldq']
        try:
            if collection.insert_one(comment):
                print('Saved to Mongo')
        except:
            print('無法保存')
    #獲取代理       
    def get_ip(self):
        url = 'http://www.xiladaili.com/http/'
        response = requests.get(url)
        t = response.text
        html = etree.HTML(t)
        result = html.xpath("http://table[@class='fl-table']/tbody/tr[{}]/td[1]/text()".format(random.randint(1,50)))
        proxy = {
                'https':str(result[0])
                }
        return proxy

if __name__ == '__main__':
    for i in range(0,500):
        if i%5 == 0:
            time.sleep(1)
            my = maoyan()
            d = my.get_comments(i,timeout=3)
            my.parse_comments(d,i)
        
    
            
        

反爬

我在get_comments()函數(shù)里寫了一大段亿虽,其實(shí)是為了更好的反爬。
首先就是請(qǐng)求頭苞也,寫上了heasers经柴、user-agentcookie,這是為了讓網(wǎng)站認(rèn)為這是一個(gè)人發(fā)送的請(qǐng)求墩朦,而不是機(jī)器坯认。
其次,這里多加了一個(gè)代理proxies

def get_ip(self):
        url = 'http://www.xiladaili.com/http/'
        response = requests.get(url)
        
        t = response.text
        html = etree.HTML(t)
        result = html.xpath("http://table[@class='fl-table']/tbody/tr[{}]/td[1]/text()".format(random.randint(1,50)))
        proxy = {
                'https':str(result[0])
                }
        return proxy

代理是通過一個(gè)免費(fèi)網(wǎng)站中獲得的氓涣,隨機(jī)取得一個(gè)ip牛哺,用于requests
雖然代碼很長,但是簡單劳吠,就是有點(diǎn)繁瑣引润。
同時(shí)在請(qǐng)求一個(gè)url后,經(jīng)常會(huì)time.sleep()痒玩,否則淳附,請(qǐng)求的太過于頻繁,就會(huì)被封的蠢古。
最后requests.get中的timeout參數(shù)可以設(shè)定等待連接的秒數(shù)奴曙,超過時(shí)間,就會(huì)拋出異常草讶。

儲(chǔ)存

這一次洽糟,我們將數(shù)據(jù)存入MongoDB

準(zhǔn)備工作

具體自行搜索啦,怎么安裝堕战,下載坤溃。

連接MongoDB

連接MongoDB時(shí),我們需要使用的是嘱丢,PyMongo庫里面的MongoClient薪介。一般來說,傳入MongoDB的ip和端口即可越驻。

import pymongo import MongoClient

client = pymongo.MongoClient(host='localhost',port=27017)

這樣就可以創(chuàng)建MoongoDB的連接對(duì)象啦汁政。
當(dāng)然我們也可以換種方式:

client = MongoClient('mongodb://localhost:27017/')

指定數(shù)據(jù)庫

MongoDB中可以建立多個(gè)數(shù)據(jù)庫道偷,接下來我們需要指定操作哪個(gè)數(shù)據(jù)庫,在這里烂完,我們以建立maoyan為例:

db = client['maoyan']

或者

db = client.maoyan

指定集合

在每個(gè)數(shù)據(jù)庫里又有許多集合(collection),它們類似于關(guān)系型數(shù)據(jù)庫中的表。

下一步就是要指定操作的集合诵棵,同樣我們建立名為lldq的集合:

collection = db['lldq']

或者

collection = db.lldq

插入數(shù)據(jù)

此時(shí)抠蚣,我們可以插入數(shù)據(jù)了。
一般數(shù)據(jù)以字典的形式表示履澳,比如我們?nèi)绻@取我們想要的id嘶窄,性別,評(píng)論距贷,分?jǐn)?shù)柄冲,等等:

comment = {'content': com['content'], 'gender': com['gender'],
'id': com['id'],
'nick': com['nick'],
'replyCount': com['replyCount'], 
'score': com['score'],
'time': com['time'], 
'upCount': com['upCount'],
'userId': com['userId'], 
'userLevel': com['userLevel']
}

諸如這種形式。
我們可以使用insert_one()insert_many()方法來插入單條和多條記錄

collection.insert_one(comment)

如果你是用的是insert_many()忠蝗,就要將數(shù)據(jù)以列表的形式傳遞现横。
比如,你有兩個(gè)字典阁最,分別為dic1,dic2戒祠,要存儲(chǔ)到mongodb

collection.insert_many([dic1,dic2])

可視化工具

最后儲(chǔ)存了一大堆,可是怎么看呢速种?
這里推薦Robo 3T,官方網(wǎng)站姜盈,三大平臺(tái)都支持,下載鏈接配阵。
另外馏颂,還有一個(gè)簡單易用的可視化工具——Studio 3T,它同樣具有方便的圖形化管理界面棋傍,官方網(wǎng)站救拉,同樣支持三大平臺(tái),下載鏈接瘫拣。

預(yù)告

接下倆近上,會(huì)講講,可視化函數(shù)拂铡,以及對(duì)這次爬取到的數(shù)據(jù)的處理壹无。
最后請(qǐng)大家批評(píng)指正!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末感帅,一起剝皮案震驚了整個(gè)濱河市斗锭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌失球,老刑警劉巖岖是,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帮毁,死亡現(xiàn)場離奇詭異,居然都是意外死亡豺撑,警方通過查閱死者的電腦和手機(jī)烈疚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聪轿,“玉大人爷肝,你說我怎么就攤上這事÷酱恚” “怎么了灯抛?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長音瓷。 經(jīng)常有香客問我对嚼,道長,這世上最難降的妖魔是什么绳慎? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任纵竖,我火速辦了婚禮,結(jié)果婚禮上杏愤,老公的妹妹穿的比我還像新娘磨确。我一直安慰自己,他們只是感情好声邦,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布乏奥。 她就那樣靜靜地躺著,像睡著了一般亥曹。 火紅的嫁衣襯著肌膚如雪邓了。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天媳瞪,我揣著相機(jī)與錄音骗炉,去河邊找鬼。 笑死蛇受,一個(gè)胖子當(dāng)著我的面吹牛句葵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兢仰,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼乍丈,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了把将?” 一聲冷哼從身側(cè)響起轻专,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎察蹲,沒想到半個(gè)月后请垛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體催训,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年宗收,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漫拭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡混稽,死狀恐怖采驻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荚坞,我是刑警寧澤挑宠,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布菲盾,位于F島的核電站颓影,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏懒鉴。R本人自食惡果不足惜诡挂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望临谱。 院中可真熱鬧璃俗,春花似錦、人聲如沸悉默。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抄课。三九已至唱星,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跟磨,已是汗流浹背间聊。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抵拘,地道東北人哎榴。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像僵蛛,于是被迫代替她去往敵國和親尚蝌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5充尉? 答:HTML5是最新的HTML標(biāo)準(zhǔn)驼壶。 注意:講述HT...
    kismetajun閱讀 27,513評(píng)論 1 45
  • 前端開發(fā)面試知識(shí)點(diǎn)大綱: HTML&CSS: 對(duì)Web標(biāo)準(zhǔn)的理解、瀏覽器內(nèi)核差異喉酌、兼容性热凹、hack泵喘、CSS基本功:...
    秀才JaneBook閱讀 2,383評(píng)論 0 25
  • HTTP基本原理 URI、URL般妙、URN(Uninform Resource) URI(Identifier):統(tǒng)...
    GHope閱讀 2,085評(píng)論 2 26
  • 面試題一:https://github.com/jimuyouyou/node-interview-questio...
    R_X閱讀 1,625評(píng)論 0 5
  • 前端開發(fā)知識(shí)點(diǎn) HTML&CSS對(duì)Web標(biāo)準(zhǔn)的理解纪铺、瀏覽器內(nèi)核差異、兼容性碟渺、hack鲜锚、CSS基本功:布局、盒子模型...
    Hebborn_hb閱讀 845評(píng)論 0 1