分析自己在大学期间读过的书(三)

前情提要

前一篇文章中,我想明白了:使用 书名 搜索,得到的豆瓣返回结果集的第一个元素其实就是目标书的信息。于是,在这一篇文章中,我将调用豆瓣 API 得到借书记录中所有的书的读书标签,并生成相应的词云。

使用豆瓣 API 根据书名搜索书

搜索豆瓣 API,找到开发者文档。豆瓣的 API 看着很清晰,一下子就找到我需要的接口。看了一下,还可以限制返回数量,于是理所当然的,将 count 限制为 1 就获取第一条数据了。

豆瓣图书搜索 API

使用 Postman 验证想法

在 Postman 中输入搜索 API,加上查询条件,发送请求,查看结果集。OK,正是我想要的。

使用 Postman 验证 API

查看 tags 对象,很好,不但有标签,还有类似权重之类的 count,可能未来还有更多的用途,目前先不管它。

获取图书所有的 tag

Javascript 代码实现获取所有 tag

写了段简单的 JS 代码,验证是否得到与 Postman 一致的结果。结果,出错了……

URL 编码问题

使用 Javascript 请求图书信息

挺奇怪的,使用的 URL 跟 Postman 的是一样的,为什么会出错呢?
看了看错误信息,status_code 是 400,请求有问题?
这个请求里面只有 URL,那就是 URL 有问题。想了想,难道是因为 URL 中的中文吗?
试着把书名改为只有英文的 Java,嘿,成功了。
那么问题就在于中文编码了。

解决

网络上搜索了一下,发现使用 Javascript 发网络请求,需要使用 encodeURI 将中文编码之后才可以正常请求。

第一次遇到 URL 编码问题是大二,后面就陆陆续续遇到同样的问题。可是到现在我也没有彻底搞明白这个问题。为什么 URL 不能有中文呢?以后可能还会遇到同样的问题,得找个机会彻底搞明白。当然,这是后话,且按下不表。

简单地写完了获取所有 tag 的代码,截取了部分书名,作为测试数据。执行 node getTags.js,成功获得数据。

速度限制

出错

将测试数据改为完整的书名列表,结果出现了错误。

很费解,看了一会儿之后,猜测是因为请求数量太多了,豆瓣把我的请求给禁掉了。

在 Postman 重新请求验证想法,发现如我所料。

{
    "msg": "rate_limit_exceeded2: 43.243.12.21",
    "code": 112,
    "request": "GET /v2/book/search"
}

查了 豆瓣的 API 文档,发现,请求确实是有限制的。

豆瓣 API 请求限制

我得到的错误信息是这个
rate_limit_exceeded 速度限制

解决方法

读书记录中的书名有两百多个,一次性发请求的话,肯定会超出限制。想了个方法,就是在每个请求前随机等待若干时间,这样或许可以避免豆瓣的请求限制。

最后的代码如下

const agent = require('superagent');
const async = require('async');
const bookTitleList = require('./book_title_list');

function sleep(milliseconds) {
  let start = new Date().getTime();
  for (let i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

function random_sleep(second) {
  sleep(Math.floor((Math.random() * second) + 1) * 1000)
}

function requestTags(bookTitle, done) {
  random_sleep(20);
  agent.get(encodeURI(`https://api.douban.com/v2/book/search?q="${bookTitle}"&count=1`))
       .end((err, res) => {
           if (err) {
             console.log(err);
           } else {
             const tag = res.body.books[0].tags;
             done(null, tag);
           }
         }
       );
}

async.map(bookTitleList, requestTags, (err, tags) => {
  tags.forEach(tag => {
    console.log(tag);
  })
});

我还没有验证它是否可以正常工作,因为限制时间还没过呢……

未完待续……

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容