使用Python搜索并抓取小红书笔记与评论

1. 写在前面

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

2. 分析加密入口

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

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

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

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

3. 使用JS注入

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

Playwright方式:

python 复制代码
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方式:

python 复制代码
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. 爬虫工程化

以笔记搜索为例,注意一下search_id是动态生成的!完整的爬虫代码实现如下所示:

python 复制代码
import json
import time
import random
import execjs
import requests

def base36encode(number, digits='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
    base36 = ""
    while number:
        number, i = divmod(number, 36)
        base36 = digits[i] + base36
    return base36.lower()

def generate_search_id():
    timestamp = int(time.time() * 1000) << 64
    random_value = int(random.uniform(0, 2147483646))
    return base36encode(timestamp + random_value)

url = 'https://edith.xiaohongshu.com/api/sns/web/v1/search/notes'
api_endpoint = '/api/sns/web/v1/search/notes'
a1_value = '' # 自行获取

search_data = {
    "keyword": "北京美食",
    "page": 1,
    "page_size": 20,
    "search_id": generate_search_id(),
    "sort": "general",
    "note_type": 0
}

headers = { 
  'sec-ch-ua': 'Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
  'Content-Type': 'application/json;charset=UTF-8',
  'sec-ch-ua-mobile': '?0',
  'Referer': 'https://www.xiaohongshu.com/',
  'sec-ch-ua-platform': 'macOS',
  'Origin': 'https://www.xiaohongshu.com',
  'Cookie': '', # 自行获取
  'User-Agent': '' # 自行获取
}

with open('xs_xsc20240219.js', 'r', encoding='utf-8') as f:
    js_script = f.read()
    context = execjs.compile(js_script)
    sign = context.call('get_xs_xsc', api_endpoint, search_data, a1_value)

headers['x-s'] = sign['X-s']
headers['x-t'] = str(sign['X-t'])
headers['X-s-common'] = sign['X-s-common']

response = requests.post(url, headers=headers, data=json.dumps(search_data, separators=(",", ":"), ensure_ascii=False).encode('utf-8'))

print(response.json())

最后,有需要的小伙伴可找作者获取开箱即用的完整爬虫项目工具!小白配置与启动方式、没有过多的繁琐配置!功能支持关键词搜索(内容与网站同步)、笔记自动抓取(从爆款自上往下)、评论内容抓取

笔记搜索抓取完成后会自动存储到本地的Excel文件内,如下所示:

笔记对应的评论内容抓取完成后同样会存储在本地的Excel文件内,如下所示:

相关推荐
HEX9CF16 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
希望有朝一日能如愿以偿31 分钟前
力扣题解(飞机座位分配概率)
算法·leetcode·职场和发展
丶Darling.43 分钟前
代码随想录 | Day26 | 二叉树:二叉搜索树中的插入操作&&删除二叉搜索树中的节点&&修剪二叉搜索树
开发语言·数据结构·c++·笔记·学习·算法
积水成江1 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
JustCouvrir1 小时前
代码随想录算法训练营Day15
算法
Z3r4y1 小时前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
小小工匠1 小时前
加密与安全_HOTP一次性密码生成算法
算法·安全·htop·一次性密码
Tandy12356_1 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
中文英文-我选中文1 小时前
排序算法的理解
算法·排序算法