Nodejs 用 request 模块遇到网站的 vue 的$nextTick(),无法获取返回数据

Nodejs 用 request 模块遇到网站的 vue 的$nextTick(),无法获取返回数据
网站: https://www.kejiwanjia.com/mission/today

现象描述:

通过 fiddler 抓包,得到该网站的签到链接为: https://www.kejiwanjia.com/wp-json/b2/v1/userMission
熟练的构造好所需的 cookie 和其他 headers ,以及 useragent 后,第二天 post 发送构造好的链接,结果一直返回前一天的签到值,登录网页后,发现实际未签到,保持网页的登录状态,返回 fiddler 再 post 一次构造链接,结果顺利签到。。。


情况分析:
分析 fiddler 抓到的相关 html 和 js 文件,发现主要的可疑点见下图


imgur.com/a/M3nZSe4


深度分析 aka 小白的一派胡言:
直接 post 发送构造链接,因为$nextTick()的存在,导致服务器无法返回最新的 response ,而是继续返回前一天签到成功后的 response


最后附上我的核心代码


imgur.com/a/5SGcCYB


希望各位大佬提供下解题思路


13 回复

和 vue 无关


好吧,我果然是在一派胡言。。。

试试把登录流程也加上呢 接口拿到实时的 token 再走 sign

有的,那个很简单就没贴,思路就是通过 username 和 password ,拿到实时 token ,拿到的 token 再传到这个 sign 函数里面,拼接成 authorization ,就可以签到了

很奇怪的地方就是,直接 post 构造链接,无论如何都不能签到,但一旦登录次,再 post 链接,马上就能签到成功

刚好最近也研究这个网站的签到,其实只需要 authorization 就行的,不需要 cookie 也能签到。不过这网站登录一次的有效时长只有 3 天左右好像。估计只能按照你上面的思路,先弄好登录这一步才行。

登录这一步,你可以在抓包时关注下含有 jwj-auth 这个关键词的网址,会有惊喜

jwt-auth

  1. 和 vue 没关系
    2. 没报 403 ,token 应该没问题
    3. 如果已经登录的直接打开页面也能签到,说明跟登录接口没什么关系,应该是有一个前置接口没有调用,而这个接口在登录状态打开页面会自动调用,可以再看看登录状态下打开页面调用了那些接口。

多谢大佬的思路,我在 fiddler 抓包时,发现登录网页后,stream 流里面还紧跟着一个登录 hi.kejiwanjia.com 链接的 login 信息,我试试把这个 login 也写进去

那就容易了,先使用 post 去登录,然后它返回的内容里有 token 的值,用 'Bearer ’ + token 就是 authorization

然后再用这个 authorization 去 post 签到的那个接口就可以了

再次感谢大佬,昨晚分析了一会,大致是这个流程(小白个人分析,不一定完全对):这个网站是先调用了 getUserMission 这个接口,获取服务器端用户的一些数据(等级,积分,用户名等等)其中包含了 mission 字段,随后再调用 UserMission 接口签到,并将签到数据写入 mission 字段,从而实现用户签到数据的更新,如果不经调用 getuserinfo 这个接口,则导致无法获得 mission 字段,进而导致签到后的数据无法写入

nexttick 的作用是等待 DOM 更新后再执行操作,你把它当成 setTimeout 来看就可以

在Node.js中使用request模块来抓取网页数据时,如果遇到Vue.js的$nextTick()方法,确实会遇到问题,因为$nextTick()是Vue.js在客户端用来确保DOM更新完成后再执行代码的机制。而request模块仅仅是发起HTTP请求并获取静态HTML内容,它无法执行或等待Vue.js在客户端执行的代码。

要解决这个问题,你有以下几种方案:

  1. 使用无头浏览器(如Puppeteer): Puppeteer可以控制Chrome或Chromium浏览器,允许你等待Vue.js完成渲染。

    const puppeteer = require('puppeteer');
    
    (async () => {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
      await page.goto('http://your-vue-app.com');
      const content = await page.content();
      console.log(content);
    
      await browser.close();
    })();
    
  2. 检查API端点: 如果Vue.js应用从服务器获取数据,尝试直接访问这些API端点,而不是抓取渲染后的HTML。

  3. 使用Selenium: 类似于Puppeteer,Selenium可以控制浏览器,但支持更多浏览器类型。

  4. 等待加载完成: 如果Vue.js应用在某个特定的时间后完成数据加载,你可以在request之后添加延时,但这通常不是可靠的方法。

建议优先考虑使用Puppeteer,因为它直接支持现代Web标准,并且与Node.js集成良好。

回到顶部