因为今年的webapp中有个功能需要根据书名搜索封面,但是市面上没有可用的开放API,于是只能自己撸一个了。
因为自己之前没有这方面的经历,同时也没有把这个服务做成怎么怎么高大上的打算。初衷就是一个开发快、查询快的单页面接口。
思路一:通过国家数字图书馆的接口
中国国家数字图书馆
中国国家数字图书馆 传送门
中国国家数字图书馆中包含了所有印刷出品书籍的副本(之前在“知网事件”中了解到),所以能不能通过调用抓包搜索接口来获取图片的封面呢?
经过测试是可行的,但是有2个缺点:
- 图片不能自定义尺寸,涉及到后期裁切API
- 国家的,风险很大
开发难度:★★★☆☆
开发速度:★★★☆☆
牢饭概率:★★☆☆☆
思路二:通过第三方的开放API平台
第三方的开放API平台
试用了几家API提供商,大多是数据不全的。有些近年来很火的玄幻、言情、都市小说根本查不到。
思路三:通过聚合抓取知名小说站点的搜索结果
抓取流程图
遍历抓取知名小说网站的结果来获取封面。
这个方法存在的缺点是:
- 抓取频率大,浪费时间多
- 后期维护成本高,对应每一个网站都要单独写抓取规则
- 部分站点存在反爬虫机制,抓取难度大
开发难度:★★★★★
开发速度:★☆☆☆☆
牢饭概率:★★★☆☆
思路四:通过搜索引擎的结果来获取
搜索引擎的结果
如某搜索引擎的第一条搜索结果会变成该小说的封面,且该图片url地址支持图片处理。即可通过url中的w和h参数来生成对应宽高的封面图,无需在代码中进行图片裁切操作。
使用该方法的好处是:
- 搜索引擎的线路好,查询速度快
- 支持url图片处理,无需再写图片裁切代码
开发难度:★☆☆☆☆
开发速度:★★★★★
牢饭概率:★☆☆☆☆
正式开工
出于某些安全原因考虑,代码就不开源了。这里只说一下几个开发要点
- 首先设置屏蔽错误和允许跨域
1 2 3 4
| <?php error_reporting(0); header('Access-Control-Allow-Origin:*'); header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE');
|
- 使用curl来做数据请求
1 2 3 4 5 6 7 8 9
| $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, "要请求的URL"); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_TIMEOUT, 10); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); $data = curl_exec($curl); curl_close($curl);
|
- 使用DOMXPATH类,通过XPATH表达式读取数据
1 2 3 4 5 6 7 8
| $libxml_previous_state = libxml_use_internal_errors(true); $domInstance = new \DOMDocument(); $domInstance->loadHTML('<?xml encoding="UTF-8">' . '网页源代码');
libxml_clear_errors(); libxml_use_internal_errors($libxml_previous_state); $XPath = new \DOMXPath($domInstance);
|
DOMXPath的用法可以看这里 传送门,主要用到的还是$XPath->query(‘XPath表达式’)。
然后遍历解析DOM元素的属性值,拿到图片url输出即可。
- 网络异常、IP被ban、获取数据失败时的错误处理
关键位置try{}catch($e){},最好设置一个默认返回值用于在异常时返回。
小结
代码量不多,50行左右就完成了一个查询封面服务。同时在代理IP池足够大的情况下完全可以保证高可用。