JB的Python之旅-爬取phizhub網站(原始碼)

jb發表於2019-03-01

前言

其實,本篇也是水文,寫這篇的原因是,有同學問要原始碼,既然這與的話,就寫一個吧;

上文連結點這裡,上文主要介紹這個網站反爬的策略,但是沒想到居然有那麼多同學看,受寵若驚;

在寫原始碼的時候,遇到一個坑,就是看到時間戳就預設是當前時間戳,結果自己坑自己了,詳情請看下面介紹吧;

文章很短且很水,一分鐘即可閱讀完;

爬取思路

爬取網站地址點這裡

多次上滑,介面地址如下:

http://www.phizhub.com/phiz/get_phiz_list/?category=-1&page=1&last_time=0&page_size=40

http://www.phizhub.com/phiz/get_phiz_list/?category=-1&page=2&last_time=1551141631000&page_size=10

http://www.phizhub.com/phiz/get_phiz_list/?category=-1&page=3&last_time=1551138631000&page_size=10

http://www.phizhub.com/phiz/get_phiz_list/?category=-1&page=4&last_time=1551120032000&page_size=10
複製程式碼

首頁這裡,不停上滑,發現就是pagelast_time在變化; 一個是頁碼,一個是時間戳;

網站裡面有不同的欄目,每個有什麼不同?

image.png-21.2kB

多次嘗試發現,不同欄目,category會不一樣,簡單分析下,這個值不是按順序固定的,好像沒辦法查?

從程式指令碼,肯定是有地方處理的,比如tabname=熱門,就返回-1的值,而且,必然是前端處理的,那一起找出來吧;

方法1:

還是老套路,F12,重新整理整個頁面

image.png-44.9kB

這裡面就有一個叫get_tabs的介面,很明顯了;

看吧,一目瞭然了;

image.png-80.6kB

方法2:

如果沒有重新整理這個頁面,是不會發現第一種方法的,在一個頁面裡面切換不同的tab,是不會再請求get_tabs介面的;

image.png-39.2kB

這種時候,怎麼辦?沒關係,一個一個看吧;

image.png-36.8kB
image.png-73.9kB
image.png-174kB

最終發現,在一個js檔案裡面有個叫tabSelected的函式,看上去就像有點關係,點選進入看看;

image.png-22kB

點選後進入的是上面的介面,好像沒太多關係,簡單滑動下?

嘖嘖嘖,就在不遠處,就看到這程式碼了;

image.png-75.2kB

這不就是我們想要的關係表嗎?

image.png-35.8kB

手動整理下,如下;

欄目名稱 category值
熱門 -1
動圖 9
圖片 4
美女 106
丘比龍 101
搞笑 104
惡搞 105
動漫 7
皮皮蝦 107
熊本 102
熊貓人 5

行吧,再分析下json,獲取image下的large或small即可;

image.png-54.5kB

然後就啪啪啪的擼碼,結果發現,不管怎麼爬,永遠都是那40張,用postman看了下,的確發現介面每次返回都一模一樣,如下:

這是第一次,page=1

image.png-23.1kB

這是第二次,page=2,但是呢,url地址跟第一次的一模一樣;

image.png-24.6kB

一開始以為是Bug,但是多次嘗試跟看回程式碼,都沒發現啥問題,那就重新正視那4個引數吧;

{'category': -1, 'page': '2', 'last_time': '1551398207276', 'page_size': '10'}


複製程式碼

categroy是欄目分類,page是頁數,page_size是請求圖片的資料,唯獨不知道last_time是什麼;

而jb的程式碼裡面,last_time用的是時間戳;

重新看介面資訊:

第一次請求:
http://www.phizhub.com/phiz/get_phiz_list/?category=-1&page=1&last_time=0&page_size=40

上滑觸發第二次請求:
http://www.phizhub.com/phiz/get_phiz_list/?category=-1&page=2&last_time=1551402631000&page_size=40
複製程式碼

一開始看到last_time就是時間戳,就沒細看,但是現在這個時間戳一看,不對啊,現在是11點,為啥顯示9點?那就是說,這個時間戳並非是當前時間戳羅!

image.png-11.4kB

換句話說,這裡面肯定是有邏輯吧,行吧,一起看看,還是老套路,看介面js,還是get_data這個,直接搜尋last_time,行吧,邏輯都出來了;

image.png-88.1kB
image.png-50.5kB

看吧,last_time就是用上一個介面的最後一個圖片的addtime做標記,怪不得會有問題;

var last = photos[count - 1];
last_time = last.addtime;
複製程式碼

修改下程式碼看看效果吧~

image.png-66kB

過程輸出:

image.png-7.8kB

原始碼:

由於是臨時做的,很不智慧,需要的同學二次封裝下吧,先簡單說說:

# 預設請求一次是40張圖片,如果需要修改,找到下方程式碼直接修改數字即可;
pz_params["page_size"] = "40"

# 分類資訊,預設熱門,需要爬全部欄目,自己寫個陣列,for即可,為啥jb不寫?因為懶;
category = -1

# 這裡是需要爬取的頁數,一次40張;
page_number = 5

# 圖片下載目錄,也可以不用管
dir = "phizhub/remen/"

複製程式碼

好吧,不墨跡,原始碼貼上:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
爬取phizhub表情網站
"""
import time
import requests
import hashlib
import json
import re
import os

# 首頁連結
pz_index_url = "http://www.phizhub.com/"

# 拼接介面地址
pz_url = pz_index_url+"phiz/get_phiz_list/"

# 請求引數的last_time,第一次是0,後面用上一個介面最後一個圖片的addtime做標記
last_time = 0;

# 欄目資訊,熱門是-1,動圖是9,圖片是4,美女是106,丘比龍是101,搞笑是104,惡搞是105,動漫是7,皮皮蝦是107,熊本是102,熊貓人是5
category = -1

# 請輸入需要爬取的頁數
page_number = 5

# 圖片下載目錄
dir = "phizhub/remen/"

# 請求頭,F12直接copy過來
pz_headers = {
    "Accept": "application/json, text/javascript, */*; q=0.01",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "Cookie": "SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1; gr_user_id=42467006-4ec0-45f7-acdc-91e4060f2262; gr_session_id_a103dce5677f1b74=75095d47-6c68-4ee7-bf81-c2c6be3ece8e; Hm_lvt_fc3add2fc30f38259191ad30ff5813c9=1550714607; gr_session_id_a103dce5677f1b74_75095d47-6c68-4ee7-bf81-c2c6be3ece8e=true; Hm_lpvt_fc3add2fc30f38259191ad30ff5813c9=1550714675",
    "Host": "www.phizhub.com",
    "Pragma": "no-cache",
    "Referer": "http://www.phizhub.com/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
    "X-Requested-With": "XMLHttpRequest",
    "Content-Type": "application/x-www-form-urlencoded",
    "sss": "{sss}",
    "timestamp": "{timestamp}"
}

# body
pz_params = {
    "category": category,
    "page": "{page}",
    "last_time": "{last_time}",
    "page_size": "{page_size}",
}

# 獲取當前時間的13位時間戳
def get_millistime():
    return str(round(time.time() * 1000))

# 獲取sss的值,sss就是phizhub_abc_+當前13位時間戳拼接而成的md5
def get_sss(time):
    str = "phizhub_abc_"+ time
    return md5Encode(str)

# 獲取md5
def md5Encode(str):
    m = hashlib.md5()
    m.update(str.encode(encoding='utf-8'))
    return m.hexdigest()


# 幹活的地方
def start_job(i):
    global last_time;

    # 頁碼從1開始算
    set_value(i)
    response = requests.get(pz_url, headers=pz_headers, params=pz_params, verify=False).json()

    # 獲取data裡面的數量,從而獲取對應的圖片連結
    count = len(response["data"])
    for page in range(count):
        print('正在下載圖片:第%s/%s張,' % (page+1, count))
        download_Image(response["data"][page]["image"]["large"])
        if (page+1 == count):

            last_time = response["data"][page]["addtime"]


# 下載圖片
def download_Image(image_link):
    if not os.path.exists(dir):
        os.makedirs(dir)

    filename = get_ImageName(image_link)
    with open(dir + filename, 'wb') as f:
        # 以二進位制寫入的模式在本地構建新檔案
        header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.32 Safari/537.36',
            'Referer': "http://www.phizhub.com/"}
        f.write(requests.get(image_link, headers=header).content)



# 獲取檔名
def get_ImageName(text):
    # http://imagecloud.phizhub.com/1551016041657_b58b2935383a11e9b160186590e027b5.gif
    pattern = re.compile("http://imagecloud.phizhub.com/")
    text = re.sub(pattern, "", text)
    return text



# 賦值
def set_value(i):
    # 賦值時間戳跟sss
    pz_params["page"] = str(i)
    time = get_millistime()
    pz_headers["timestamp"] = time
    pz_headers["sss"] = get_sss(time)
    pz_params["last_time"] = last_time
    pz_params["page_size"] = "40"

if __name__ == '__main__':
    for i in range(1,page_number+1):
        print("現在爬第%s頁" % i)
        start_job(i)


複製程式碼

小結

再次證明這是水文吧,沒啥好總結的,就是看到時間戳別想當然是當前時間戳;

謝謝大家~

JB的Python之旅-爬取phizhub網站(原始碼)

相關文章