JB的Python之旅-爬取phizhub网站(源码)

栏目: Python · 发布时间: 5年前

内容简介:其实,本篇也是水文,写这篇的原因是,有同学问要源码,既然这与的话,就写一个吧;上文链接点这里,上文主要介绍这个网站反爬的策略,但是没想到居然有那么多同学看,受宠若惊;在写源码的时候,遇到一个坑,就是看到时间戳就默认是当前时间戳,结果自己坑自己了,详情请看下面介绍吧;

其实,本篇也是水文,写这篇的原因是,有同学问要源码,既然这与的话,就写一个吧;

上文链接点这里,上文主要介绍这个网站反爬的策略,但是没想到居然有那么多同学看,受宠若惊;

在写源码的时候,遇到一个坑,就是看到时间戳就默认是当前时间戳,结果自己坑自己了,详情请看下面介绍吧;

文章很短且很水,一分钟即可阅读完;

爬取思路

爬取网站地址点这里;

多次上滑,接口地址如下:

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 在变化; 一个是页码,一个是时间戳;

网站里面有不同的栏目,每个有什么不同?

JB的 <a href='https://www.codercto.com/topics/20097.html'>Python</a> 之旅-爬取phizhub网站(源码)

多次尝试发现,不同栏目, category 会不一样,简单分析下,这个值不是按顺序固定的,好像没办法查?

从程序脚本,肯定是有地方处理的,比如 tabname=热门 ,就返回 -1 的值,而且,必然是前端处理的,那一起找出来吧;

方法1:

还是老套路, F12,刷新整个页面

JB的Python之旅-爬取phizhub网站(源码)

这里面就有一个叫 get_tabs 的接口,很明显了;

看吧,一目了然了;

JB的Python之旅-爬取phizhub网站(源码)

方法2:

如果没有刷新这个页面,是不会发现第一种方法的,在一个页面里面切换不同的tab,是不会再请求 get_tabs 接口的;

JB的Python之旅-爬取phizhub网站(源码)

这种时候,怎么办?没关系,一个一个看吧;

JB的Python之旅-爬取phizhub网站(源码)
JB的Python之旅-爬取phizhub网站(源码)
JB的Python之旅-爬取phizhub网站(源码)

最终发现,在一个js文件里面有个叫 tabSelected 的函数,看上去就像有点关系,点击进入看看;

JB的Python之旅-爬取phizhub网站(源码)

点击后进入的是上面的界面,好像没太多关系,简单滑动下?

啧啧啧,就在不远处,就看到这代码了;

JB的Python之旅-爬取phizhub网站(源码)

这不就是我们想要的关系表吗?

JB的Python之旅-爬取phizhub网站(源码)

手动整理下,如下;

栏目名称 category值
热门 -1
动图 9
图片 4
美女 106
丘比龙 101
搞笑 104
恶搞 105
动漫 7
皮皮虾 107
熊本 102
熊猫人 5

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

JB的Python之旅-爬取phizhub网站(源码)

然后就啪啪啪的撸码,结果发现,不管怎么爬,永远都是那40张,用postman看了下,的确发现接口每次返回都一模一样,如下:

这是第一次, page=1

JB的Python之旅-爬取phizhub网站(源码)

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

JB的Python之旅-爬取phizhub网站(源码)

一开始以为是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点?那就是说,这个时间戳并非是当前时间戳罗!

JB的Python之旅-爬取phizhub网站(源码)

换句话说,这里面肯定是有逻辑吧,行吧,一起看看,还是老套路,看接口js,还是 get_data 这个,直接搜索 last_time ,行吧,逻辑都出来了;

JB的Python之旅-爬取phizhub网站(源码)
JB的Python之旅-爬取phizhub网站(源码)

看吧, last_time 就是用上一个接口的最后一个图片的 addtime 做标记,怪不得会有问题;

var last = photos[count - 1];
last_time = last.addtime;
复制代码

修改下代码看看效果吧~

JB的Python之旅-爬取phizhub网站(源码)

过程输出:

JB的Python之旅-爬取phizhub网站(源码)

源码:

由于是临时做的,很不智能,需要的同学二次封装下吧,先简单说说:

# 默认请求一次是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网站(源码)

以上所述就是小编给大家介绍的《JB的Python之旅-爬取phizhub网站(源码)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

矩阵计算

矩阵计算

Gene H. Golub、Charles F. Van Loan / 袁亚湘 / 人民邮电出版社 / 2009 / 89.00元

本书是国际上数值计算方面的权威著作,有“圣经”之称。被美国加州大学、斯坦福大学、华盛顿大学、芝加哥大学、中国科学院研究生院等很多世界知名学府用作相关课程的教材或主要参考书。 本书系统地介绍了矩阵计算的基本理论和方法。书中的许多算法都有现成的软件包实现,每节后还附有习题,并有注释和大量参考文献,非常有助于自学。一起来看看 《矩阵计算》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试