helloWorld
Posted deppwang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了helloWorld相关的知识,希望对你有一定的参考价值。
---
title: 如何查找某个网站的(如:有道云笔记)的接口
english_title: how-to-find-the-api-of-a-website-eg-note-youdao-com
date: 2020-06-11 20:48:37
tags: [有道云笔记, 接口]
categories: 网络
---
开发了个 《一键导出 / 备份「有道云笔记」所有笔记》的[脚本](https://github.com/DeppWang/youdaonote-pull)。主要原理是利用有道云笔记本身的接口。下面是根据正常用户操作逻辑,找到需要的接口,主要是登录和「下载」。
## 一、登录
登录的目的是获取 Cookie
### 1.1 找登录接口
![技术图片](https://image.cha138.com/20210819/05b6e8a0cbf944538216d5d6924d926e.jpg)
接口应该在登录时执行。使用**错误密码**测试,可得到登录 post 请求接口。注意过滤条件是 All
```
https://note.youdao.com/login/acc/urs/verify/check?app=web&product=YNOTE&tp=urstoken&cf=6&fr=1&systemName=&deviceType=&ru=
https://note.youdao.com/signIn//loginCallback.html&er=
https://note.youdao.com/signIn//loginCallback.html&
vcode=dman9&systemName=mac&deviceType=MacPC×tamp=1591770253472
```
### 1.2 推导密码加密规则
![image-20200610142935436](https://deppwang.oss-cn-beijing.aliyuncs.com/blog/2020-06-10-062936.png)
本地测试使用同样错误密码用不同加密算法加密,看加密结果是否一致
发现使用 md5 加密
```python
## Python
password=hashlib.md5(password.encode(‘utf-8‘)).hexdigest()
```
### 1.3 找返回验证登录状态 Cookie 的接口
![技术图片](https://image.cha138.com/20210819/9871e850b60e42b58a0dc6a9d2a1d7d7.jpg)
登录成功后,会返回验证登录状态的 Cookie。接口应该在登录成功后执行。发现跳转首页后第一个 XHR 接口中包含验证登录状态的 Cookie,YNOTE_CSTK
```
https://note.youdao.com/yws/mapi/user?method=get&multilevelEnable=true
```
## 二、「下载」
### 2.1 找返回根目录 id 的接口
![技术图片](https://image.cha138.com/20210819/a6e34563bde846cc82c636064be92f5a.jpg)
我们根据一个笔记 URL 可以看出,URL 里包含了父文件夹 id 和当前文件 id。「我的文件夹」下的 test.md 的 URL:
```
https://note.youdao.com/web/#/file/F83DF1ADA69344D194C7CE861D09B1A1/note/WEB4aa8bf8074d61befea1dd20f5593f01c/
```
「我的文件夹」 是根目录,它的 id 是 `F83DF1ADA69344D194C7CE861D09B1A1`,下面称它为 root_id。
我们推测,有道云笔记是设计是根据文件夹 id,获取文件夹下的所有文件信息(打开文件夹,可看到文件夹下的文件)。所以我们需要先得到 root_id。当登录成功后,跳转到首页时,应该有接口能得到 root_id。
测试发现下面接口返回值包含 root_id:
```
https://note.youdao.com/yws/api/personal/file?method=getByPath&keyfrom=web&cstk=01PvSwwu
```
![技术图片](https://image.cha138.com/20210819/c73f90dbca1a4553bd11af6de15dc7a0.jpg)
接口返回格式类似这样:
```json
{
"fileEntry":{
"userId":"m17191082115@163.com",
"id":"F83DF1ADA69344D194C7CE861D09B1A1", // root_id
"version":22888,
"name":"ROOT",
"parentId":"0",
"createTimeForSort":1497860357,
"modifyTimeForSort":1497860357,
....
},
"fileMeta":{
"chunkList":"None",
"sharedCount":0,
"title":"ROOT",
...
},
...
}
```
```python
root_id = response.content[‘fileEntry‘][‘id‘]
```
### 2.2 找获取目录下所有文件信息的接口
![技术图片](https://image.cha138.com/20210819/6efd80a584594d69848564b36853f84b.jpg)
有了 root_id,需要找到根据 id 获取目录下所有文件信息的接口。
接口应该在打开文件夹时执行。点击某一个文件夹,测试发现包含当前目录所有文件信息的接口为:
```
https://note.youdao.com/yws/api/personal/file/9d8a2385eeec77338211b4f04bbf844d?all=true&f=true&len=30&sort=1&isReverse=false&method=listPageByParentId&keyfrom=web&cstk=01PvSwwu
```
接口返回格式跟上面差不多,只是数量更多,属性多了 parentId(父文件夹 id)。
```json
[
{
"fileEntry":{
"userId":"m17191082115@163.com",
"id":"9d8a2385eeec77338211b4f04bbf844d",
"version":14168,
"name":"来自手机",
"parentId":"F83DF1ADA69344D194C7CE861D09B1A1", // 父文件夹的 id,此时是 root_id
"createTimeForSort":1550712995,
"modifyTimeForSort":1550713003,
....
},
"fileMeta":{
"chunkList":null,
"sharedCount":0,
"title":"来自手机",
"fileSize":0,
...
},
...
}
...
]
```
### 2.3 找到获取文件内容的接口
![技术图片](https://image.cha138.com/20210819/714d288fadd344a58c309ece18bc9cf7.jpg)
通过文件夹 id 得到了文件 id(fileId),需要找到根据 fileId 获取文件内容的接口。
接口应该在点击笔记标题得到笔记内容时执行。点击某一篇笔记标题,可以找到获取文件内容的接口:
```
https://note.youdao.com/yws/api/personal/sync?method=download&keyfrom=web&cstk=01PvSwwu
```
## 三、模拟浏览器操作
### 3.1 设置请求头
随便哪个页面(如:首页 `https://note.youdao.com/`)可以看到请求头包含下面这些内容:
![技术图片](https://image.cha138.com/20210819/070427da44a74bb2abbd636179513c0e.jpg)
取一部分设置即可
```python
class YoudaoNoteSession(requests.Session):
def __init__(self):
self.headers = {
‘User-Agent‘: ‘Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36‘,
‘Accept‘: ‘*/*‘,
‘Accept-Encoding‘: ‘gzip, deflate, br‘,
‘Accept-Language‘: ‘zh-CN,zh;q=0.9,en;q=0.8‘,
}
```
### 3.2 模拟「进入网页版」
![技术图片](https://image.cha138.com/20210819/7c625876520845099f27f56f9000b2d7.jpg)
```Python
self.get(‘https://note.youdao.com/web/‘)
```
点击「进入网页版」,会重定向到登录页面
### 3.3 模拟打开登录页
![技术图片](https://image.cha138.com/20210819/608514c11dd641ec886897e22c704e5a.jpg)
```Python
self.get(‘https://note.youdao.com/signIn/index.html?&callback=https%3A%2F%2Fnote.youdao.com%2Fweb%2F&from=web‘)
```
跳转登录页后,要执行下面 3 个接口:
```python
self.get(‘https://note.youdao.com/login/acc/pe/getsess?product=YNOTE&_=‘ + timestamp())
self.get(‘https://note.youdao.com/auth/cq.json?app=web&_=‘ + timestamp())
self.get(‘https://note.youdao.com/auth/urs/login.json?app=web&_=‘ + timestamp())
```
## 四、结语
根据找到的接口,模拟用户操作也有不少应用场景。除了开发像这种导出文件的脚本,可以开发一切你想自动化执行的操作。比方 cnblogs、juejin 发文章等。比较麻烦的就是像上面这样找接口了,可以先看看有没有人有过总结。
也可以利用一些浏览器的 API,如 [Puppeteer](https://github.com/puppeteer/puppeteer),它提供一个真实的浏览器环境,可以真正模拟用户操作,不需要找到所有接口,只需要设置网页 url,以及设置需要操作的「按钮」属性。因为提供浏览器环境,它属于重量级操作。可以看看 [ArtiPub](https://github.com/crawlab-team/artipub) 如何使用 Puppeteer。这种方式有点不好的地方就是平台可能改前端属性,需要注意更新。
全文完。
!--cnblogs.com>!--有什么不明白的看看[源码](http://github.com/DeppWang/youdaonote-pull/blob/master/pull.py)就知道了。-->!--只需要有>!--more-->以上是关于helloWorld的主要内容,如果未能解决你的问题,请参考以下文章
Spring《二》 Bean的生命周期
Express学习笔记
第3章:Maven使用入门/3.3 编写测试代码
快乐水题1816. 截断句子
cordova 3.0:Android:未定义连接
仅从另一个联接表中选择第一行