人群看板需求分析
先找到策略中心具体的数据。对应数据库中的数据
看看接口是否需要被逆向
-
点开消费者细分,可以找到人群包(人群名称)
-
点击查看透视
label字段分类:
在这里插入图片描述
预测年龄:tagTitle
苹果id(perspecttaskId)——>详细标签数据信息接口
负载信息
响应数据信息
{
"rate": 20.955497819874278,
"tagValue": "917007982",
"count": -1,
"nullCount": 0,
"nullRate": 0,
"nullEncryptedCount": 0,
"tagName": "daas_tag_pred_age_level_20200415093010",
"tagValueName": "[18,24]"
}
——>苹果ID接口(id)
响应数据信息
{
"throwed": false,
"gmtModified": 1689168616000,
"statusInfo": "",
"isReplace": false,
"description": "",
"crowdAdbStatus": 1,
"baseId": "026130413",
"source": "STRATEGY_CUSTOM",
"isThrowed": false,
"uniMemberReportAuth": null,
"syncValid": true,
"inheritable": false,
"rootSource": null,
"gmtUpdate": 1689168616000,
"uniMemberReportInfo": null,
"validInDatahub": false,
"perspective": 1,
"id": 66703384,
"gmtUpdateReal": null,
"blurred": true,
"statusInfoCode": 0,
"category2": "STRATEGY_CUSTOM",
"category3": "STRATEGY_CUSTOM",
"canUpdate": false,
"crowdDivisionStatus": null,
"reportId": 7744917,
"category1": "STRATEGY_CUSTOM",
"withConditionGroup": true,
"count": 22000,
"gmtCreate": 1689168568000,
"customType": "",
"fullLinkPlatform": "NOT_FULL_LINK",
"brandId": "64284",
"updateSettedFlag": false,
"name": "苹果已购人群-23-6",
"reportStatusInfo": "",
"sourceName": null,
"smartId": 914,
"projectId": 183575,
"status": "CREATED"
},
问题
在做完上述分析之后我很疑惑,这个获取详细标签数据信息的接口总是刷新不出来。如果一个网站的接口,刷新之后就找不到了,是什么原因呢?和缓存有关系吗?。。。后来发现这不是普通的HTTP爬虫啦。换了一种协议传输数据。
后续的分析我们着重讲一下案例的原理和实战干货。因为博主很苦逼的研究了一周,发现网上关于websocket的案例实在不多,大多都是讲原理,那咋不去教前端捏。哈哈。少有的案例,不是国外的网站,就是需要加密破解。正好。因为网站的特殊性,没有对相关的请求信息做加密处理。所以可以很纯粹的给大家讲讲websocket非异步爬虫实战,分享一下我辛苦一周钻研出来的小小心得。
浅浅展示一下博主努力做案例的过程。
看到这里麻烦点个赞和关注,精彩的要来了
websocket爬虫
原理:
我特意做了一个流程图,因为我发现很多博文中都把websocket请求和接收数据的过程原理化了,这样实际调用的方法和实际操作不能匹配。这也是我困扰很久的地方。
WS协议请求demo
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws, close_status_code, close_msg):
print("### closed ###")
def on_open(ws):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send("Hello %d" % i)
time.sleep(1)
ws.close()
print("thread terminating...")
_thread.start_new_thread(run, ())
# wss://ws-insight-engine.tmall.com/
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp(
"wss://ws-insight-engine.tmall.com/", on_open=on_open,
on_message=on_message, on_error=on_error, on_close=on_close
)
ws.run_forever()
- 定义了
on_message
函数,它在WebSocket客户端接收到来自服务器的消息时被调用。接收到的消息作为参数message
传入,并被打印出来。 - 定义了
on_error
函数,它在WebSocket客户端遇到错误时被调用。错误信息作为参数error
传入,并被打印出来。 - 定义了
on_close
函数,它在WebSocket连接关闭时被调用。它打印出一条消息表示连接已关闭。 - 定义了
on_open
函数,它在WebSocket连接成功打开后被调用。在这个函数内部,定义了一个名为run
的嵌套函数,它将在一个新的线程中执行。 - 在
run
函数中,使用了一个循环来连续发送三条消息到WebSocket服务器。每条消息发送后,线程休眠1秒。发送完所有消息后,线程再次休眠1秒,然后关闭WebSocket连接,并打印出一条消息表示线程正在终止。 - 在
on_open
函数中,使用_thread.start_new_thread
启动了一个新线程来运行run
函数。 - 在
if __name__ == "__main__":
块中,这是Python中的常用模式,用于判断当前脚本是否作为主程序运行。 websocket.enableTrace(True)
启用了调试输出,这将打印出所有WebSocket事件的详细信息,帮助调试。- 创建了一个
WebSocketApp
实例,指定了WebSocket服务器的URL(“wss://ws-insight-engine.tmall.com/”),并将之前定义的事件处理函数(on_open
,on_message
,on_error
,on_close
)绑定到相应的事件上。 - 调用
ws.run_forever()
开始运行WebSocket事件循环,这将保持连接开启直到它被关闭。
资料
关于WebSocket协议的爬虫资料,这里有一些有用的资源:
1. **Python—WebSocket爬虫实战原创**:介绍了WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议,并提供了一个实战案例。[查看详情](https://blog.csdn.net/weixin_43060843/article/details/104798541)
2. **【JS 逆向百例】WebSocket 协议爬虫,智慧树扫码登录案例分析**:分析了WebSocket协议简称为WS或者WSS(WebSocket Secure),并通过智慧树扫码登录案例进行了详细的讲解。[查看详情](https://cloud.tencent.com/developer/article/1914104)
3. **websocket与爬虫 - 高金的博客**:讨论了WebSocket是一种在单个TCP连接上进行全双工通讯的协议,以及它与爬虫的关系。[查看详情](https://igaojin.me/2018/02/04/websocket%E4%B8%8E%E7%88%AC%E8%99%AB/)
4. **WebSocket爬虫与JS逆向实战原创**:提供了一个基于Java的WebSocket爬虫示例,用于模拟客户端请求服务器,建立WebSocket连接,抓取对方数据。[查看详情](https://blog.csdn.net/Fleehom/article/details/133887962)
5. **基于websocket爬虫- Sgoyi**:讨论了爬虫面对HTTP和WebSocket的情况,以及如何使用Python中的网络请求库进行模拟发送网络请求。[查看详情](https://www.cnblogs.com/yhll/p/10709593.html)
6. **WebSocket在爬虫中的应用与实践**:介绍了WebSocket是一种网络通信协议,允许在单个TCP连接上进行全双工通信,在爬虫中的应用与实践。[查看详情](https://cloud.baidu.com/article/2927136)
这些资料涵盖了WebSocket协议的基本概念、与爬虫的结合使用,以及一些实战案例。希望这些资源能够帮助你更好地理解和应用WebSocket协议进行爬虫开发。
Sec-WebSocket-Key分析
根据你的需求,关于`Sec-WebSocket-Key`及其逆向工程的资料,这里有一些相关的中文资源:
1. [【JS 逆向百例】WebSocket 协议爬虫,智慧树扫码登录案例分析](https://juejin.cn/post/7038882823780417544) - 这篇文章详细分析了WebSocket协议在实际应用中的一个案例,包括`Sec-WebSocket-Key`的作用和如何在服务端处理这个密钥。
2. [WebSocket协议浅析](https://itimetraveler.github.io/2018/10/27/WebSocket%E5%8D%8F%E8%AE%AE%E6%B5%85%E6%9E%90/) - 这篇文章提供了对WebSocket协议的基础分析,包括`Sec-WebSocket-Key`和`Sec-WebSocket-Accept`的作用,以及它们如何帮助提供基础的防护,减少恶意连接和意外连接。
3. [一文了解WebSocket 协议](https://makonike.github.io/2023/05/06/%E4%B8%80%E6%96%87%E4%BA%86%E8%A7%A3WebSocket%E5%8D%8F%E8%AE%AE/index.html) - 这篇文章讨论了WebSocket协议的基本概念,包括`Sec-WebSocket-Key`和`Sec-WebSocket-Accept`的角色和作用。
4. [What is Sec-WebSocket-Key for?](https://stackoverflow.com/questions/18265128/what-is-sec-websocket-key-for) - 虽然这是一个英文资源,但它详细解释了`Sec-WebSocket-Key`的作用,这个头部字段是在WebSocket开放握手中从客户端发送到服务器的,用于提供握手的一部分验证。
`Sec-WebSocket-Key`是WebSocket握手过程中的一个重要组成部分,它是由客户端生成的一个Base64编码的随机字符串。服务器接收到这个密钥后,会按照特定的算法处理并返回一个加密的`Sec-WebSocket-Accept`响应头,这个过程是为了验证连接确实是WebSocket连接,防止非WebSocket连接的恶意请求。理解这一机制对于进行WebSocket通信和相关逆向工程非常重要。
Sec-WebSocket-Key
是WebSocket握手过程中的一个重要组成部分,它是由客户端生成的一个Base64编码的随机字符串。服务器接收到这个密钥后,会按照特定的算法处理并返回一个加密的Sec-WebSocket-Accept
响应头,这个过程是为了验证连接确实是WebSocket连接,防止非WebSocket连接的恶意请求。理解这一机制对于进行WebSocket通信和相关逆向工程非常重要。
以下是一些中文资料,您可以通过这些资料深入了解WebSocket协议中`Sec-WebSocket-Accept`值的生成过程及其重要性:
1. [WebSocket协议浅析](https://itimetraveler.github.io/2018/10/27/WebSocket%E5%8D%8F%E8%AE%AE%E6%B5%85%E6%9E%90/) - 这篇文章提供了对WebSocket协议的基础分析,包括`Sec-WebSocket-Accept`和`Sec-WebSocket-Key`的作用。
2. [响应头'Sec-WebSocket-Accept'的生成原创](https://blog.csdn.net/moasp/article/details/119915825) - 这篇文章详细讲解了`Sec-WebSocket-Accept`的生成原理和过程。
3. [你不知道的Websocket协议,这次给你讲明白!](https://www.51cto.com/article/774923.html) - 这篇文章全面介绍了WebSocket协议的握手过程,包括`Sec-WebSocket-Accept`值的作用。
这些资料将帮助您更好地理解WebSocket协议的工作原理,特别是握手阶段`Sec-WebSocket-Accept`值的生成和验证过程。
代码解析学习:
异步websocket爬虫:
# pip install websockets
import websockets
import asyncio
import requests
# 发送 加密参数
def req_html():
# 写翻页功能
res = requests.get('https://api.waitwaitpay.com/api/vendors/nearby?keyword=%E7%82%B8%E9%B8%A1&latitude&longitude&page=1&request_id=-1&type=search&with_vouchers=false',headers={
'user-agent':'adasdasdasd'
})
return res
async def echo(websocket):
message = '我是发送给客户端的信息'
# 发送数据
# 可以给他传 密文 发送给浏览器解密
res = req_html()
sent_text = res.text
await websocket.send(sent_text)
return True
# 接收 客户端返回的数据
async def recv_msg(websocket):
while 1:
# 接收
resv_text = await websocket.recv()
print(resv_text)
with open('sss.txt','w',encoding='utf-8') as f:
f.write(resv_text)
# 入口
async def main_run(websocket):
await echo(websocket)
await recv_msg(websocket)
stat_sever = websockets.serve(main_run,'127.0.0.1',9999)
print('成功建立连接')
loop = asyncio.get_event_loop()
loop.run_until_complete(stat_sever)
# 保持长连接 需要不断的监听返回的数据
loop.run_forever()
目标:
- 找到接口了,响应的data值是加密后的。请求值也是加密的。(先尝试解密,不行的话可以看视频学补环境)
wss_url = f"wss://www.jdz.gov.cn/1ywuKELSO2ahQuWZ/pr/{dGg2aCfMMK97Ro270mqBFu5qjC8TQbL2opnHvbEpM}/b/ws/{tableid}/{FW9uCWqlVzC22m1KfCMCjfvFHpRMsgt}"
{dGg2aCfMMK97Ro270mqBFu5qjC8TQbL2opnHvbEpM}:Tifz8hd5p4O3AB%2BivrbJpAQR5gK2baZcp_zGlOnSooM%3D
{tableid}:kmz6tx452s
{FW9uCWqlVzC22m1KfCMCjfvFHpRMsgt}:6727e0bb-2881-405a-8056-6fa8b01d8581
结果发现这里URL中加密的字段有两个都能在cookie信息中找到,说明是自动生成的。
报错:
- 错误的消息格式:客户端发送给服务器的消息格式可能不正确,不符合服务器期望的格式。这可能包括错误的数据编码、不正确的消息结构等。
- 服务器内部错误:服务器在处理客户端的WebSocket请求时内部出现错误,导致无法正确处理请求。
下面是分析过程。后续会优化,有需要的找我要。
测试:苹果兴趣人群-23-8
接口为:https://strategy.tmall.com/api/scapi?path=/api/v1/custom/listPerspective
响应信息如下:
{
"throwed": false,
"gmtModified": 1693274807000,
"statusInfo": "",
"isReplace": false,
"description": "",
"crowdAdbStatus": 1,
"baseId": "026130413",
"source": "STRATEGY_CUSTOM",
"isThrowed": false,
"uniMemberReportAuth": null,
"syncValid": true,
"inheritable": false,
"rootSource": null,
"gmtUpdate": 1693274807000,
"uniMemberReportInfo": null,
"validInDatahub": false,
"perspective": 1,
"id": 67080221,
"gmtUpdateReal": null,
"blurred": true,
"statusInfoCode": 0,
"category2": "STRATEGY_CUSTOM",
"category3": "STRATEGY_CUSTOM",
"canUpdate": true,
"crowdDivisionStatus": null,
"reportId": 7905461,
"category1": "STRATEGY_CUSTOM",
"withConditionGroup": true,
"count": 3500000,
"gmtCreate": 1693274697000,
"customType": "",
"fullLinkPlatform": "NOT_FULL_LINK",
"brandId": "64284",
"updateSettedFlag": false,
"name": "苹果兴趣人群-23-8",
"reportStatusInfo": "",
"sourceName": null,
"smartId": 914,
"projectId": 183575,
"status": "CREATED"
},
苹果兴趣人群-23-8和 苹果已购人群-23-6
test = {
"method": "/iSheetCrowdService/offline",
"headers": {
"rid": "171386533324303",
"type": "PULL",
"bizType": "STRATEGY"
},
"body": {
"args": {
"id": "661",
"perspectTaskId": "67080221",
"bizParam": {
"crowdIds": [
"67080221"
],
"tagList": [
"daas_tag_pred_age_level_20200415093010"
]
},
"appId": "209"
}
}
}