使用Python爬取小红书笔记与评论(js注入方式获取x-s)

news2024/11/17 5:34:59

文章目录

  • 1. 写在前面
  • 2. 分析加密入口
  • 3. 使用JS注入
  • 4. 爬虫工程化

【作者主页】:吴秋霖
【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作!
【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建与开发实战》
还有未来会持续更新的验证码突防、APP逆向、Python领域等一系列文章

1. 写在前面

  除了对x-s、x-s-common进行分析实现加密算法,还有之前文章中提到的通过JS注入免扣加密算法的方式获取加密参数

加密分析及算法文章请阅读这篇文章:小红书x-s、x-s-common加密分析(2024-01-10更新)

x-s的加密算法为JS实现、x-s-common的加密算法为Python实现

2. 分析加密入口

在这里插入图片描述

可以看到上图断点处l包含x-s跟x-t的返回,看下面这行代码:

l = (a && void 0 !== window._webmsxyw ? window._webmsxyw : encrypt_sign)(s, i) || {};

window._webmsxyw函数内即加密逻辑,在自执行函数内部并添加在了window属性中

该函数接受两个参数,s是api接口的路径,i是请求提交的参数

3. 使用JS注入

可以使用Playwright或者pyppeteer实现,通过浏览器的JavaScript注入来获取加密参数,代码实现分别如下

Playwright方式:

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch(headless=True)
        page = await browser.new_page()
		# 注入stealth.min.js脚本
        await page.add_init_script(path="stealth.min.js")
        url = "" # 请求api
        data = "" # 请求参数

        # 执行JavaScript
        encrypt_params = await page.evaluate('([url, data]) => window._webmsxyw(url, data)', [url, data])
        local_storage = await page.evaluate('() => window.localStorage')

        print(encrypt_params)
        print(local_storage)

        await browser.close()
        
asyncio.run(main())

pyppeteer方式:

import asyncio
from pyppeteer import launch

async def main():
    browser = await launch(headless=True)
    page = await browser.newPage()

    # 注入stealth.min.js脚本
    stealth_script = open("stealth.min.js", "r").read()
    await page.evaluateOnNewDocument(stealth_script)

    url = ""  # 请求api
    data = ""  # 请求参数

    # 执行JavaScript
    encrypt_params = await page.evaluate('([url, data]) => window._webmsxyw(url, data)', [url, data])
    local_storage = await page.evaluate('() => window.localStorage')

    print(encrypt_params)
    print(local_storage)

    await browser.close()

asyncio.get_event_loop().run_until_complete(main())

上面的stealth.min.js脚本注入的作用是为了防止被检测的,另外cookie参数需要设置属性来避免Web端出现滑动验证码

当然,这个都是爬虫最终工程化需要考虑的事情,这里主要还是通过非逆向分析的方式去解决加密参数问题!

window.localStorage在之前加密分析的文章中已经详细介绍了,localStorage是一个在浏览器中存储键值对的API,通常用于持久化地存储数据,所需的b1参数就在其中

JS注入方式运行结果如下所示:
在这里插入图片描述

x-s跟x-t的加密参数通过注入的方式能够直接拿到,但是x-s-common的参数仍需要通过sign的方法加密计算生成!

Python版本的sign加密算法在之前的加密分析文章中已提供!JS注入的方式主要为了获取这些个参数:x-s、x-t、b1

JS注入的方式对于有前端基础及经验的小伙伴,就很简单了。通过上面的方式获取到所有的加密参数后,接下来就是爬虫的工程化

4. 爬虫工程化

以笔记搜索为例,爬虫代码实现如下:

import json
import httpx
from typing import Dict, Optional

async def request(self, method, url, **kwargs) -> Dict:
    async with httpx.AsyncClient(proxies=self.proxies) as client:
        response = await client.request(
            method, url, timeout=self.timeout,
            **kwargs
        )   
    data: Dict = response.json()
    if data["success"]:
        return data.get("data", data.get("success", {}))
    elif data["code"] == self.IP_ERROR_CODE:
        raise IPBlockError(self.IP_ERROR_STR)
    else:
        raise DataFetchError(data.get("msg", None))

async def unified_request(self, 
	uri: Optional[str] = None, 
	data: Optional[dict] = None,
	keyword: Optional[str] = None,
	page: Optional[int] = 1, 
	page_size: Optional[int] = 20,
	sort: Optional[SearchSortType] = SearchSortType.GENERAL,
	note_type: Optional[SearchNoteType] = SearchNoteType.ALL) -> Dict:
    
    if keyword:
        _host = "https://edith.xiaohongshu.com"
        uri = "/api/sns/web/v1/search/notes"
        data = {
            "keyword": keyword,
            "page": page,
            "page_size": page_size,
            "search_id": get_search_id(),
            "sort": sort.value,
            "note_type": note_type.value
        }
    elif uri and data:
        headers = await self._pre_headers(uri, data)
        json_str = json.dumps(data, separators=(',', ':'), ensure_ascii=False)
        return await self.request(method="POST", url=f"{self._host}{uri}",
                                  data=json_str, headers=headers)
    else:
        raise ValueError("Either 'uri' and 'data' or 'keyword' must be provided.")

    return await request(method="POST", url=f"{_host}{uri}", data=json.dumps(data), headers=await self._pre_headers(uri, data))

最后,订阅的小伙伴可找作者获取开箱即用的完整爬虫项目代码,如下:

JS注入方式笔记搜索:

在这里插入图片描述

JS注入方式笔记评论:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1376497.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

可运营的SSL证书在线生成系统源码,附带图文搭建教程

安装教程 运行环境 PHP8.0.2-8.2最好选用8.0 Nginx1.22.1版本 Mysql5.7 伪静态设置为Thinkphp 后台账号admin 密码123456 系统使用API申请地址:https://www.sslprogen.com/

pybind11实现numpy和OpenCV Mat的数据交互

1、编译安装pybind11 下载源代码:https://github.com/pybind/pybind11, 文档:https://pybind11.readthedocs.io/en/stable/compiling.html 解压后进入到命令行,如果有conda环境,就先进入想要的conda环境&#xff0c…

Unity 工具 之 Azure 微软连续语音识别ASR的简单整理

Unity 工具 之 Azure 微软连续语音识别ASR的简单整理 目录 Unity 工具 之 Azure 微软连续语音识别ASR的简单整理 一、简单介绍 二、实现原理 三、注意实现 四、实现步骤 五、关键脚本 一、简单介绍 Unity 工具类,自己整理的一些游戏开发可能用到的模块&#x…

用MATLAB求最短路径(graphshortestpath)和求最小生成树(minspantree),代码演示

求最短路径(graphshortestpath),求最小生成树(minspantree) 文章目录 求最短路径(graphshortestpath),求最小生成树(minspantree)1、最短路径问题2、最小生成…

写点东西《Docker入门(下)》

写点东西《Docker入门(下)》 Docker ComposeDocker 注册表Docker 引擎Linux 容器和 Windows 容器的概念:容器编排Docker SwarmDocker Compose Docker Compose 是一个方便的工具,可帮助您轻松运行和连接不同的软件服务,就好像它们都是同一事件的一部分一样。 Docker Compo…

【设计模式】01-前言

23 Design Patterns implemented by C. 从本文开始,一系列的文章将揭开设计模式的神秘面纱。本篇博文是参考了《设计模式-可复用面向对象软件的基础》这本书,由于该书的引言 写的太好了,所以本文基本是对原书的摘抄。 0.前言 评估一个面向对…

C++力扣题目111--二叉树的最小深度

力扣题目链接(opens new window) 给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明: 叶子节点是指没有子节点的节点。 示例: 给定二叉树 [3,9,20,null,null,15,7], 返回它的最小深度 2 思路 看完了这篇104.二…

RuntimeError: Placeholder storage has not been allocated on MPS device!解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Web安全测试基础

SQL注入 当下最常用的一个攻击手段,就是通过SQL命令插入到Web表单中或页面请求查询字符串中,最终达到欺骗服务器执行恶意的SQL语句的目的,SQL注入一旦成功,轻则直接绕开服务器验证,直接登录成功,重则将服务…

Stream流递归查询部门树

Java 递归查询树是很常见的功能,也有很多写法,小编这里记录stream流递归部门树写法,自从小编用上stream流之后,是爱不释手,的确是个不错的好东西,话不多说,直接上代码 第一步:先创建…

用通俗易懂的方式讲解:大模型 RAG 技术,从入门到精通

本文基于IVAN ILIN发布于Towards AI的博客[1]进行总结归纳,感谢原作者的精彩讲解。 检索增强生成(Retrieval Augmented Generation,简称RAG)为大型语言模型(LLMs)提供了从某些数据源检索到的信息&#xff0…

RISC-V是如何与X86、ARM三分天下

目录 1.行业CPU指令集格局 2.汽车中的RISC-V进展 2.1 国际进展 2.2 国内进展 3.小结 2023年3月2日,在平头哥牵头举办的玄铁RISC-V生态大会上,工程院院士倪光南表示,基于RISC-V模块化、可扩展、容易定制、不受垄断制约等优势,…

2019年认证杯SPSSPRO杯数学建模C题(第一阶段)保险业的数字化变革全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 基于 CART 决策树和 SVR 的客户续保概率预测 C题 保险业的数字化变革 原题再现: 车险,即机动车辆保险。保险自身是一种分散风险、消化损失的经济补偿制度,车险即为分散机动车辆在行驶过程中可能发作的未知风…

SpringBoot多环境配置Maven Profile组

Maven profile组 注意切换配置时 mvn clean下 或者 clean 加install 或者compile 编译 clean之后 install下 或者compile 编译 nohup java -Xms256m -Xmx512m -Dfile.encodingUTF-8 -jar demo.jar --spring.profiles.activeprod > system.log 2>&1 &

2024年A特种设备相关管理(电梯)证考试题库及A特种设备相关管理(电梯)试题解析

题库来源:安全生产模拟考试一点通公众号小程序 2024年A特种设备相关管理(电梯)证考试题库及A特种设备相关管理(电梯)试题解析是安全生产模拟考试一点通结合(安监局)特种作业人员操作证考试大纲…

Word不同部分(分节)设置页眉和页码的使用指南——附案例操作

Word页眉和页码分节设置的使用指南 目录 Word页眉和页码分节设置的使用指南摘要1. 插入分节符2. 设置不同的页眉3. 设置不同的页码4. 调整页码的起始值5. 删除或更改分节6. 预览和调整 摘要 在撰写word文档时,我们经常需要在不同的部分应用不同的页眉和页码格式。在…

靶机实战(10):OSCP备考之VulnHub Tre 1

靶机官网:Tre: 1[1] 实战思路: 一、主机发现二、端口发现(服务、组件、版本)三、漏洞发现(获取权限) 8082端口/HTTP服务 组件漏洞URL漏洞(目录、文件)80端口/HTTP服务 组件漏洞URL漏…

基于JAVA+ssm开发的在线报名系统设计与实现【附源码】

基于JAVAssm开发的在线报名系统设计与实现【附源码】 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系统 …

前端页面优化做的工作

1.分析模块占用空间 new (require(webpack-bundle-analyzer).BundleAnalyzerPlugin)() 2.使用谷歌浏览器中的layers,看下有没有影响性能的模块,或者应该销毁没销毁的 3.由于我们页面中含有很大的序列帧动画,所以会导致页面性能低&#xff0…

JavaScript系列——Promise

文章目录 概要Promise三种状态状态改变Promise链式调用Promise处理并发promise.all()promise.allSettled()Promise.any()promise.race() 小结 概要 Promise中文翻译过来就是承诺、预示、有可能的意思。 在JavaScript里面,Promise 是一个对象…