今日頭條爬蟲解析

如今自媒體風生水起,很多人開始入住各大自媒體平臺進行自媒體創(chuàng)作。想要持續(xù)的輸出高質量的文章太難了,于是很多人就開始搞起了偽原創(chuàng),拿別人比較熱的文章過來改一改,不僅輕松還能收獲一票粉絲,偏題了,我不是鼓勵大家搞偽原創(chuàng)。今天我們的主題是爬蟲,既然自媒體平臺有這么多高質量的文章,想要一一收藏太難了,于是就想出了通過網絡爬蟲將感興趣的文章爬取下來然后進行收藏,豈不是很爽,于是開始動手。今天拿今日頭條練手。

第一步分析入口,今日頭條的文章入口主要分為頻道入口,搜索入口,用戶主頁入口,那么我們就一一開始破解。

首先從頻道入口下手,分析網頁結構,發(fā)現(xiàn)所有的文章都是通過ajax動態(tài)加載,那么第一想法是通過selenium模擬瀏覽器進行網頁提取,雖然目的可以達到但是效果不理想,需要處理分頁去重而且效率不高,故這個方案放棄,在接著進行分析ajax接口,貌似行得通,架起代碼開始測試,在處理ajax接口是發(fā)現(xiàn)需要處理as,cp,_signature 三個參數(shù),接口如下

https://www.toutiao.com/api/pc/feed/?category=news_tech&utm_source=toutiao&widen=1&max_behot_time=0&max_behot_time_tmp=0&tadrequire=true&as=A125AB7BC7F0F59&cp=5BB7802FF5896E1&_signature=NOFpxAAAb1yLl5gie2NwDTThad

as,cp網上已經有大神破解了算法如下;

    def getASCP(self):
        t = int(math.floor(time.time()))
        e = hex(t).upper()[2:]
        m = hashlib.md5()
        m.update(str(t).encode(encoding='utf-8'))
        i = m.hexdigest().upper()

        if len(e) != 8:
            AS = '479BB4B7254C150'
            CP = '7E0AC8874BB0985'
            return AS, CP

        n = i[0:5]
        a = i[-5:]
        s = ''
        r = ''
        for o in range(5):
            s += n[o] + e[o]
            r += e[o + 3] + a[o]

        AS = 'A1' + s + e[-3:]
        CP = e[0:3] + r + 'E1'
        return AS, CP

比較難搞的是signature參數(shù),雖然網上也有很多人發(fā)文怎么破解,但是效果都不理想,只能拿到第一次請求的signature,第二次請求就直接不行了。分析js發(fā)現(xiàn)signature的請求是通過window.TAC.sign方法產生,而這個方法是動態(tài)綁定的,由一堆看不清邏輯的字符串通過一定的算法解密后得到,著手分析了一下,發(fā)現(xiàn)里面用到了Date ,Convas 相關的函數(shù),姑且進行了一下推斷,判斷入?yún)⒌臅r間戳跟當前的時間戳進行對比,肯定不能大于當前的時間,但是范圍也不能相差太遠否則一個頻道頁內容直接就爆了,對于Convas 可能就是為了限定上下文,否則為什么我們通過python直接執(zhí)行TAC.sign方法產生的signature在第二次就會失效,雖說第一次能請求成功那么我們是不是每次都模擬第一次請求,雖說也能得到數(shù)據(jù),但不能連續(xù)采集還是有點失望的。那有沒有其他的辦法可以解決了,在經過一下午的思考過后發(fā)現(xiàn),既然在保證上下文的情況下可以連續(xù)采集(通過chrome的console生成的signature是可以的)那么我們通過selenium方案來模擬上下文,負責產生signature,剩下的就是通過urllib來請求接口獲取數(shù)據(jù)進行解析是否可以行了?經過一番驗證結果是可喜的,功夫不負有心人達到目的。直接貼代碼。代碼中有些自有邏輯沒有貼出來,但是邏輯思路基本上都有了。今天到此為止,下次說怎么爬詳情


    def get_channel_data(self, page):  #獲取數(shù)據(jù)
        req = self.s.get(url=self.url, verify=False, proxies=get_proxy_ip())
        #print (self.s.headers)
        #print(req.text)
        headers = {'referer': self.url}
        max_behot_time='0'
        signature='.1.hXgAApDNVcKHe5jmqy.9f4U'
        eas = 'A1E56B6786B47FE'
        ecp = '5B7674A7FF2E9E1'
        self.s.headers.update(headers)
        item_list = []
        browser = webdriver.Chrome()
        browser.implicitly_wait(10)
        browser.get(self.url)
        for i in range(0, page):

            Honey = json.loads(self.get_js())
            # eas = self.getHoney(int(max_behot_time))[0]
            # ecp = self.getHoney(int(max_behot_time))[1]
            eas = Honey['as']
            ecp = Honey['cp']
            signature = Honey['_signature']
            if i > 0:
                signature = browser.execute_script("return window.TAC.sign("+ max_behot_time +")")
            url='https://www.toutiao.com/api/pc/feed/?category={}&utm_source=toutiao&widen=1&max_behot_time={}&max_behot_time_tmp={}&tadrequire=true&as={}&cp={}&_signature={}'.format(self.channel,max_behot_time,max_behot_time,eas,ecp,signature)
            req=self.s.get(url=url, verify=False, proxies=get_proxy_ip())
            time.sleep(random.random() * 2+2)
            # print(req.text)
            # print(url)
            j=json.loads(req.text)
            for k in range(0, 10):
                item = toutiaoitem()
                now=time.time()
                if j['data'][k]['tag'] != 'ad' or j['data'][k]['tag'] != 'ad.platform.site':
                    item.title = j['data'][k]['title']  ##標題
                    item.source = j['data'][k]['source']  ##作者
                    item.source_url = 'https://www.toutiao.com/'+j['data'][k]['source_url']   ##文章鏈接
                    item.media_url = 'https://www.toutiao.com/'+j['data'][k]['media_url']  #作者主頁
                    item.article_genre = j['data'][k]['article_genre']  #文章類型
                    try:
                        item.comments_count = j['data'][k]['comments_count']  ###評論
                    except:
                        item.comments_count = 0

                    item.tag = j['data'][k]['tag']  ###頻道名
                    try:
                        item.chinese_tag = j['data'][k]['chinese_tag']   ##頻道中文名
                    except:
                        item.chinese_tag = ''
                    try:
                        item.label = j['data'][k]['label']  ## 標簽
                    except:
                        item.label = []
                    try:
                        item.abstract = j['data'][k]['abstract']  ###文章摘要
                    except:
                        item.abstract = ''
                    behot = int(j['data'][k]['behot_time'])
                    item.behot_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(behot))  ####發(fā)布時間
                    item.collect_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(now))  ##抓取時間
                    item.item_id = j['data'][k]['item_id']
                    try:
                        item.image_list = j['data'][k]['image_list']
                    except:
                        item.image_list = []
                    item.image_url = j['data'][k]['image_url']
                    item.middle_image = j['data'][k]['middle_image']
                item_list.append(item)
            toutiaodb.save(item_list)
            time.sleep(2)
            max_behot_time = str(j['next']['max_behot_time'])
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,592評論 25 707
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,765評論 2 59
  • 最近一直在學習python的scrapy框架。寫了比較多的小例子。工欲善其事必先利其器。今天描述的就是爬取今日頭條...
    Evtion閱讀 7,389評論 6 6
  • 你走了一個寒冬來這里賞花, 花期已過。 你,不必嘆息。 你背著行囊去遠方追逐夢想, 似夢非夢。 你,不...
    稚兮閱讀 365評論 0 0
  • 孫小猛~河北惠友集團 【日精進打卡第107天】 【知~學習】 《六項精進》3遍 共321遍 《大學》3遍 共321...
    亮亮sxm閱讀 215評論 0 0