用nodejs配合python破解X-Ca-Signature,抓取博客积分数据

世界上最稀缺的资源是时间。

在某一瞬间我惊恐得发现,一生三万天,已过三分之一,念及年少不更事,蹉跎而过,觉得心中有愧。至今无建树,脑袋里想起一句话,“不因虚度年华而悔恨,也不因碌碌无为而羞耻”。

如今发起少年狂,对一切都感起兴趣,深知往者不可谏,来着犹可追。空有胸中之宏远,奈何路漫漫其修远,深感无力,只有择一事,写点博客吧!来一点点弥补辜负的少年时光。

准备

安装nodejs,安装fiddler,配置抓取https(后来我想到可以直接用chrome的network抓啊,fiddler抓https主要还是用于手机端

nodejs网上教程,很容易安装,fiddle配置https有点复杂,需要字节创建个fiddler证书,网上有教程,本人配置了好久才成功,而且只能抓chrome的https,mozilla浏览器仍然不行

用nodejs的原因是本来我已经安装好了,而且node里面用npm下载cropto-js比较方便,这个库可以用来模拟csdn的X-Ca-Signature参数的。X-Ca-Signature用的算法是HmacSHA256。要是能知道原理,也可以通过python直接写出来,关于HmacSHA256也值得另外写篇博客进行研究。不过有现成我就直接拿来用了。

在系统某个地方安装crypto-js,再创建一个js用于模拟X-Ca-Signature,本人创建的路径是D:\nodejsProject\csdn_blog_static

npm install crypto-js

在这里插入图片描述


积分接口

登陆CSDN,进入数据观星->博文数据在这里插入图片描述

配置好fiddler的https抓包后(chrome的network也可以),进入数据观星的博客数据,抓包结果如图
在这里插入图片描述

一般的网站只需要把报文头复制过来即可模拟登陆状态获取接口数据,但CSDN的报文里面有2个值是随时变化且只能用一次的。X-Ca-Nonce和X-Ca-Signature,因此每次请求接口这2个值需要自己计算。

通过chrome的devtool经过不断关键字匹配,终于匹配到这2个值计算的关键js文件。app.js 估计是业务代码 , chunk_vendors.js 估计是一些库的合并打包。这2个js是压缩过并且混淆过的,我们可以通过chrome自带的Pretty print让其更容易看,但是混淆过的变量方法名无法恢复复,只能辛苦下。

经过一番debugger,X-Ca-Nonce的生成方法是
在这里插入图片描述
X-Ca-Signature的方法是
在这里插入图片描述

b方法最终调用

var R = s.a.HmacSHA256(h, a)S = R.toString(s.a.enc.Base64);

HmacSHA256参数h是报文头的一部分再加上X-Ca-Nonce,a是appSecret固定值,后期估计会变。经尝试,成功写出相应的js代码:
在这里插入图片描述

至此,我们可以开始我们的抓取代码编写。


代码

nodejs

csdn_HmacSHA256.js:

var Crypto = require('crypto-js');


var nonceFunc = function() {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function(e) {
            var n = 16 * Math.random() | 0
              , t = "x" === e ? n : 3 & n | 8;
            return t.toString(16)
        }
    ));
}
var nonce = nonceFunc(), appSecret = "9znpamsyl2c7cdrr9sas0le9vbc3r6ba", h="";


h += "".concat("GET", "\n");
h += "".concat("application/json, text/plain, */*", "\n");
h += "".concat("", "\n");
h += "".concat("", "\n");
h += "".concat("", "\n");

h += "x-ca-key:203803574\n";//目前看来也是固定值
h += "x-ca-nonce:" + nonce + "\n";
h += "/blog-console-api/v1/data/blog_statistics"


var hash = Crypto.HmacSHA256(h, appSecret);
var hashInBase64 = Crypto.enc.Base64.stringify(hash);
console.log(nonce);
console.log(hashInBase64);

python

CsdnKiramario.py:

import urllib.request
import urllib.parse
import os
import gzip
import json
import datetime
from openpyxl import load_workbook

class CsdnKiramario(object):

    def __init__(self):
   		#执行nodejs
        output = os.popen('node D:\\nodejsProject\\csdn_blog_static\\csdn_HmacSHA256.js')
		#读取nodejs种console输出,不是很严谨
        nonce = output.readline()
        signature = output.readline()
		
		#报文
        targetUrl = 'https://bizapi.csdn.net/blog-console-api/v1/data/blog_statistics'
        headers = {
            'Host': ' bizapi.csdn.net',
            'Connection': 'keep-alive',
            'sec-ch-ua': '"Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"',
            'X-Ca-Signature-Headers': 'x-ca-key,x-ca-nonce',
            'X-Ca-Signature': signature.strip(),
            'X-Ca-Nonce': nonce.strip(),
            'sec-ch-ua-mobile': '?0',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
            'Accept': ' application/json, text/plain, */*',
            'X-Ca-Key': ' 203803574',
            'Origin': 'https://mp.csdn.net',
            'Sec-Fetch-Site': 'same-site',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Dest': 'empty',
            'Referer': 'https//mp.csdn.net/console/dataWatch/analysis/allarticle',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            "Cookie": "替换成自己的cookie"
        }
        self.req = urllib.request.Request(url=targetUrl,method='GET', headers=headers)

    def run(self):
        res = ""
        # 爬取
        with urllib.request.urlopen(self.req) as f:
            res = f.read()
		
        ret = gzip.decompress(res).decode("utf-8")
        ret =  json.loads(ret)


        data = ret['data']
        analysDict = {}
        for statistic in data:
            name = (statistic['name'])
            num = statistic['num']
            analysDict[name] = num
		
		# 存入博客xlsx
        analysHeader = ["日期", "文章总数", "粉丝数", "点赞数", "评论数", "访问量", "积分", "收藏数", "总排名"]
        sourcePath = "D:\\麦芒\\私域计划\\博客\\博客数据.xlsx"
        wb = load_workbook(sourcePath)
        ws_active = wb['Sheet']
        row = []
        for headerName in analysHeader:
            if headerName == "日期":
                row.append(datetime.date.today().strftime("%Y/%m/%d"))
            else:
                row.append(analysDict[headerName])
        ws_active.append(row)
        wb.save(sourcePath)


if __name__ == "__main__":
    instance = CsdnKiramario()
    instance.run()

执行后
在这里插入图片描述


更多方法

不想手动执行的话,把python脚本加入windows执行计划,每天执行也可以。

参考博客
https://blog.csdn.net/DylanYuan/article/details/81533105
https://www.cnblogs.com/ruiy/p/6422586.html

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值