【无标题】


title: CSDN逆向
date: 2021-12-13 22:32:05
tags: js 爬虫逆向


CSDN逆向分析思路

1.先定义表结构

注意事项
  • char类型,要设置最大的长度
  • 对于无法确定最大长度的 可以设置为text类型
  • 设计表的时候,采集到的数据经量格式化
  • default值尽量设置,null=true
from peewee import *

db = MySQLDatabase('spider',host='localhost',port=3306,user='root',password='1234')


class BaseModel(Model):
  
    class Meta:
        database = db # This model uses the "people.db" database. 这张表对应哪个库

class Topic(BaseModel):
    title = CharField()
    Content = TextField()
    id = IntegerField()
    author = CharField()
    create_time = DateTimeField()
    answer_nums = IntegerField(default=0)
    chick_nums = IntegerField(default=0)
    praised_nums = IntegerField(default=0)


class Answer(BaseModel):
    topic_id = IntegerField()
    author = CharField()
    create_time = DateTimeField()
    Content = TextField()
    praised_nums = IntegerField()

class Author(BaseModel):
    name = CharField()
    id = IntegerField()
    chick_nums = IntegerField()  # 访问数
    original_nums = IntegerField(default=0) # 原创数
    rate = IntegerField(default=-1) # 排名
    answer_nums = IntegerField(default=0) # 评论数
    praised_nums = IntegerField(default=0) # 获赞数
    
    desc = TextField(null=True) # 描述
    industry = CharField(null = True) # 关注的标签
    followers = IntegerField(default=0) #粉丝数
    
if __name__ == '__main__':
    # 创建出框架
     db.create_tables([Topic,Answer,Author])

2.简单确定反爬步骤

  • 当我们拿到一个网站,首先可以尝试查看页面源代码 看是否包含

  • 查看所有js文件 搜索关键词 如果有则证明写在js文件中

  • 刚开始没有 极有可能在点击之后出现 在all里面可以找到data

  • 分析url的构成 尝试写代码 发送请求获取响应

    import requests
    url = "https://bizapi.csdn.net/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=4"
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36"
    }
    
    resp = requests.get(url,headers=headers)
    print(resp.status_code)
    # 400 
    
  • 当加入了UA等常参数 仍然返回错误状态码时,采用暴力操作,将请求头全部加入 HTTP是无状态协议 也就是只要我能模仿出参数 浏览器就会通过

  • 可是运行之后 我们发现返回403 表示没有权限

  • 此时我们分析一下请求 不可能通过通用的一些协议来反爬 关键是找我们不熟悉的 以下四个我们不熟悉

    x-ca-key: 203899271
    x-ca-nonce: 036b20a8-ee16-4537-b475-ac9c7dbc7865
    x-ca-signature: QyWaJYtvndqtkQbBjvgniTMk69WaSD9r3sjPMcGZ5uc=
    x-ca-signature-headers: x-ca-key,x-ca-nonce
    

    一个判断方法是 参数是否固定 此时我们用无痕浏览重新打开网页 此时参数如下

    x-ca-key: 203899271
    x-ca-nonce: d00c7765-1d7b-4d5f-b5dc-4f348346b948
    x-ca-signature: eGrfMJvN+t9hftBqcbXBHoMSUpst+9ybt2KrRm4LJQg=
    x-ca-signature-headers: x-ca-key,x-ca-nonce
    

    我们发现 x-ca-nonce --暂时的 临时的只使用一次的 x-ca-signature --签名 这两个值不是固定的 也就是说这就是反爬的点

  • 我们此时的任务是:分析那个临时参数怎么来的 签名咋来的

    (ps:签名是浏览器校验身份的一种密钥)

  • 拿着x-ca-signature 去js文件一个一个找

  • 可是我们发现 是被压缩过的 此时打开 headers 找域名csdnim.cn 打开sources 找到这个域名的文件 打开

    可以发现 是通过p函数的

  • 在想进入的函数打个断点

  • 在界面随便点进去一个 发现进入调试模式 此时进入函数内部 step into

  • 如果此函数实现 没有其它函数 可以直接使用python模拟生成

import execjs
nonce_func =execjs.compile("""p = function(e) {
            var t = e || null;
            return null == t && (t = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function(e) {
                var t = 16 * Math.random() | 0;
                return ("x" === e ? t : 3 & t | 8).toString(16)
            }
            ))),
            t
        }""")
print(nonce_func.call("p", ))



# 2840f71f-8c29-4df1-ab90-8d519ca25fc2
  • 通过调试 看看他的算法实现

i:bK9jk5dBEtjauy6gXL7vZCPJ1fOy076H 固定的


"GET
application/json, text/plain, */*



x-ca-key:203899271
x-ca-nonce:21b07f14-581f-49e3-b1e0-30b3d7b5e028
/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=1"
  • 传递两个参数就可得到

  • 接着就是用python去模拟这些算法 得到返回值,然后赋值给headers中的内容

  • import requests
    
    import execjs
    from base64 import b64decode, b64encode
    import hmac
    import hashlib
    
    
    # 一个密钥
    nonce_func = execjs.compile("""
     p = function(e) {
        var t = e || null;
        return null == t && (t = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function(e) {
            var t = 16 * Math.random() | 0;
            return ("x" === e ? t : 3 & t | 8).toString(16)
        }
        ))),
        t
    }
    """)
    
    
    
    def gen_sign(nonce_str,url):
    
        data = "GET\n"
        data +="application/json, text/plain,*/*\n"
        data += "\n\n\n"
        # data += "\n"
        # data += "\n"
        data += "x-ca-key:203899271\n"
        data += "x-ca-nonce:{}\n".format(nonce_str) 
        data += url
        print(data)
    
        # "/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=3"
        # data = 'GET\napplication/json, text/plain,*/*\n\n\n\nx-ca-key:203899271\nx-ca-nonce' \
        #        f':{nonce_str}\n/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=3'
    
    
        app_secret_key =  "bK9jk5dBEtjauy6gXL7vZCPJ1fOy076H"
    
        data = data.encode("utf-8")
        sign = b64encode(hmac.new(app_secret_key.encode('utf-8'),data,digestmod=hashlib.sha256).digest()).decode()
        return sign
    
        
    
    
    
    
    template ="""GET
    application/json, text/plain,*/*
    
    
    
    x-ca-key:203899271
    x-ca-nonce:49d2d8b8-f978-4291-8cdc-4d6d4ef2b732
    /community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=5"""
    # 
    url = "/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=3"
    nonce_str = nonce_func.call("p",)
    # print("随机值"+nonce_str)
    headers = {
    
       
    "accept": "application/json, text/plain,*/*",
    "accept-encoding": "gzip, deflate, br",
    "accept-language": "zh-CN,zh;q=0.9",
    "origin":"https://bbs.csdn.net",
    "referer":"https://bbs.csdn.net/forums/qing_gee?category=4",
    "sec-ch-ua": """Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96" """,
    "sec-ch-ua-mobile":"?0",
    "sec-ch-ua-platform": "Windows", 
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-site",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36",
    "x-ca-key": "203899271",
    "x-ca-nonce": nonce_str, # nonce 随机的 只使用一次
    # 签名
    "x-ca-signature": gen_sign(nonce_str,"/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=3"), # 签名 算法+密钥
    "x-ca-signature-headers": "x-ca-key,x-ca-nonce", # 固定
    }
    # print("签名"+gen_sign(nonce_str,'/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=3'))
    
    url = 'https://bizapi.csdn.net/community-cloud/v1/homepage/community/by/tag?deviceType=PC&tagId=3'
    resp = requests.get(url,headers=headers)
    print(resp.status_code)
    print(resp.text)
    
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小 澜 同 学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值