一键采集文章(之前一篇从CSDN扒文章的浏览器体验插件的逻辑)
优采云 发布时间: 2021-11-13 13:15一键采集文章(之前一篇从CSDN扒文章的浏览器体验插件的逻辑)
之前写过一篇文章的浏览器插件,可以一键下载掘金文章。后来,我把目光投向了CSDN。文章由于历史原因,写在CSDN,虽然之前的文章没那么好,但毕竟是自己写的,也是一个标记,所以我也想下载
其实我在CSDN文章写过一篇关于文章的文章,但是那篇文章的操作方法体验不是很好。作为浏览器插件使用会更方便。只是出于某些原因我没有考虑这一点。
使用浏览器插件从任何博客网站中取用文章的最简单方法是通过插件直接获取当前页面的DOM元素,并转换为markdown或保存它在本地。它只需要两个步骤。
它更复杂。如果要保存文章中引用的图片,则需要进行额外的图片处理。
最后,如果你想逐字逐句下载你原来的模型,逻辑会比较多(直接下载页面DOM的文本信息或者转成markdown下载,肯定会缺少精度)
现在我们在做这件事,一定要按照最高的标准去做,就是能下载图片就下载,能得到原文就得到原文。
直观点就是这张图:
这时候就想,既然所有的博客网站芭文章都有类似的流程,就多处理几个网站吧。最终插件支持掘金和CSDN。文章四大博客网站、开源中国、博客园的下载功能
插件源码已经放在github上。如果你有兴趣,你可以尝试一下。如果你不知道怎么安装这种本地插件,可以看我贴的沸点。
CSDN
大致流程和我写的浏览器插件类似,可以一键下载掘金文章,先写下载当前文章的逻辑
如果当前文章是我的,我已经登录了,那么为了得到最准确的原文信息,需要请求编辑文章界面,这样会保存文章 你原来保存的界面。@文章原文回传
于是我去看看csdn的界面。界面很容易找到。然后我复制了这个链接,继续写逻辑,但是写完测试,突然发现403界面。
我以为是因为我没有带饼干。我看到请求体中的cookies都在那里。更让人困惑的是,我直接在浏览器中请求了这个链接,但是没有用,所以直接在开发者工具里改了。csdn发起的普通请求Copy as fetch,即复制一个一模一样的请求,包括header、referrer等,然后在浏览器中执行这个请求,结果还是403
这时,我意识到这不应该是我的问题了。以为之前遇到过csdn给图片加防盗链的问题,所以觉得csdn应该对接口进行一定程度的加密。
我仔细查看了我复制的请求内容,发现headers中有四个属性很奇怪:x-ca-key、x-ca-nonce、x-ca-signature、x-ca-signature-headers
这四个header属性不是标准属性,而是想加了,属性名也很有方向性,貌似是用来加密的
反复刷新编辑页面,发现对于完全相同的请求,在每个请求的header中,四个属性中的x-ca-key和x-ca-signature-headers是固定的,x-ca-nonce和x -ca-signature 会变,所以我以为这两个值可能是其他接口返回的,但是看了所有页面相关的接口,发现没有相关信息。既然不是后端返回的,那么就只能由前端生成了
全局搜索x-ca-,一键查找,四个属性的赋值逻辑都写到一起了。
正如你可能猜到的,x-ca-key 和 x-ca-signature-headers 是硬编码的,而 x-ca-nonce 和 x-ca-signature 有其他的计算逻辑。
先看x-ca-nonce的计算,通过xCaNonce()的一个方法得到,看这个方法
此方法再次调用 createUuid。看名字就可以猜出这个方法是做什么的。
看完这个方法,我就很熟悉了。是一种生成uuid的方法,所以每次发送请求,值都不一样,才有意义。只需复制此方法并使用它来生成x-ca。-nonce
接下来,让我们看看 x-ca-signature。计算逻辑稍微复杂一些。首先,调用 xCaSignature() 方法。
这种方法比较复杂。中间的很多逻辑都是用来计算一些中间值的。直接向后看,并从最终结果向后工作。
看这一段:
var xCaSignature = function xCaSignature(_ref) { // ...
var hash = __WEBPACK_IMPORTED_MODULE_3_crypto_js___default.a.HmacSHA256(textToSign, appSecret); var signature = hash.toString(__WEBPACK_IMPORTED_MODULE_3_crypto_js___default.a.enc.Base64); return signature;
};复制代码
__WEBPACK_IMPORTED_MODULE_3_crypto_js___default对象中的crypto_js字符,以及后面的HmacSHA256方法,应该是crypto-js的组合,所以猜测这应该是关键的加密逻辑
appSecret 是一个固定字符串 9znpamsyl2c7cdrr9sas0le9vbc3r6ba,什么是 textToSign?
它看起来很像通过连接请求头中的一些数据而形成的字符串。试了几次,就确定了。该字符串的第二行是固定的。然后往下走 x-ca-key :203803574 这一行也是固定字符,下一行其实就是上面计算出来的x-ca-nonce的kv字符串和它的值。这时候再回头看xCaSignature()方法就很清楚了。好人,代码写了很多,就是为了拼接这个字符串
计算hash后,再次进行base64加密,然后将结果作为x-ca-signature的值返回
搞清楚逻辑后,我去下载了crypto-js,然后按照上面的逻辑验证了一下,流程就跑了。至此,四个加密的头部属性已经获得。
csdn的这种加密确实增加了爬取文章的难度,但加密逻辑应该只能出自搬砖的普通业务程序员之手。关键代码没有经过混淆和压缩,稍加分析即可快速处理。思路清晰,当然,他们的目的可能只是这个,只要稍微提高一下门槛,过滤掉一些人,毕竟前端加密本来就是不可靠的,没必要费劲这种低投资回报率的问题
但我仍然不明白一件事。有权编辑文章的人必须是文章的所有者。加密编辑界面的目的是什么?阻止我爬取自己的 文章?
接下来的过程和我写的浏览器插件基本一样,可以一键下载掘金文章,就不赘述了。
开源中国(osChina)
开源中国不加密接口,但是比较麻烦的一点是它的文章链接格式很多,即使是同一篇文章文章,如果从不同的入口进入,链接是其实都可以不同
没有必要详尽列出这些条目格式。你只需要保证支持大部分文章,即文章详情页链接是这两种格式:对应,文章作者主页和文章@ > 列表页等页面也对应两种路由格式。这个对应关系是有规则的,所以只要一开始就确定使用哪种格式,跟着
博客园(cnblogs)
博客园的技术栈应该比较老。页面基本都是服务端渲染返回的,ajax接口很少。连编辑页面的数据都是由服务器返回然后前端进行数据切分和格式化,所以这块逻辑需要单独处理
并且编辑页的域名和文章详情页的域名不一样。插件在文章详情页发起编辑页面请求。其实是跨域的,所以只好加了一个插件可以无限制的跨域后台脚本,然后在获取一些图片的cotent-type的时候就想到了跨域的问题,所以我也用了后台脚本来解决它。
另外,博客园的大版本改动应该比开源中国还多。文章详情页的链接格式不止一种(不知道有多少种)。更何况博客园的页面好像是可以自定义页面布局之类的。总之,很难用统一的逻辑来处理所有页面。有很多情况。我只能一一解决。至于我没有遇到的场景。,插件肯定处理不了。如果您在使用时遇到问题,可以提出问题。最好带上导致问题的文章链接,方便定位处理
概括
插件的技术难度不大,但是处理的情况比较多。虽然我已经尽可能的测试了,但是可能还有一些场景没有验证,所以可能还是会出现一些问题。如果遇到问题,请提 issue 或 PR
该插件目前支持掘金、CSDN、开源中国、博客园四大网站文章的下载功能。其实不管下载什么技术网站,文章,一般的处理流程都是一样的,就是开头的图片
所以除了这四个网站之外,其他网站理论上也可以利用目前*敏*感*词*。欢迎有兴趣的同学继续共同搭建这个插件