python 解析JS爬漫画堆 - ANXIETIER/Manhuadui GitHub Wiki

一、爬虫解析部分

源码从知乎文章那直接拿来的,原文链接在此: python解析JS爬取漫画网站--动态爬虫 解析JS的思路都在他(Dmaple)文章里,我就不多说了(嗐,我也说不明白)

就说说我踩到的坑吧:

1.上哪找帖子中所说的js文件:

按F12审查元素,按如下两个图来操作,就能看到对应文件名后有路径,再根据路径就能找到文件,右键保存就行了

第一步

第二步

2.关于decrypt20180904.js的修改:

decrypt20180904函数的修改就直接复制原贴中所提供的源码。

crypto-js.js文件中的代码不能按照Dmaple所说直接放到decrypt20180904函数下面,否则等运行的时候会报错:

execjs._exceptions.ProgramError: ReferenceError: CryptoJS is not defined

因此需要进行调整: crypto-js.js文件里面东西很多,我本身并不熟悉js的语法,看不懂这个匿名函数在网页中怎么运作的,于是我将其进行简化,删掉所有功能,只留下大体函数结构

(function () {
	}
}(this, function (){
	return CryptoJS 
}));

查了一下之后得知,这部分是JS的自执行函数,直接将这部分放到Chrome控制台中会自动执行,而具名函数放到控制台中只有你调用的时候才会执行

//具名函数
function h(){
	return 'xxx'
}
//自执行函数
(function () {
	return 'ooo'
}())

两个函数执行结果

那么处理方法就很明了了,把匿名函数改成具名函数 Crypto_JS(),大致看了crypto-js.js文件中的代码,实际上 function (root, factory){} 部分不需要,只需要14行以下的部分,翻到最下面可以看到return CryptoJS语句,当时就在这里找到的解决前文所述报错的线索

将 decrypt20180904 函数按照原贴改了之后在最前面加一句

var CryptoJS = Crypto_JS()

可用的decrypt20180904函数就像这样

function decrypt20180904(chapterImages) {
	var CryptoJS = Crypto_JS()
	//下面的是原贴中的代码
    var key = CryptoJS.enc.Utf8.parse("123456781234567G");  //十六位字符作为密钥
    var iv = CryptoJS.enc.Utf8.parse('ABCDEF1G34123412');
    var decrypt = CryptoJS.AES.decrypt(chapterImages,key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
    var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    //chapterImages = JSON.parse(decryptedStr.toString());
    return decryptedStr
}


/***********************************
	crypto-js.js文件的14行为
	}(this, function () {
	要抽离的函数就是这个function (){}
***********************************/
function Crypto_JS() {
	/**********************************
	这部分为该函数的代码块,就不贴出来了,太多
	**********************************/
	//最重要的一句就是这个返回了
	return CryptoJS;
}

到此为止,JS解析部分就完全搞定了

二、代理部分

代理使用socks5代理,本来我啥也不会,看了另一个知乎文章学习了一下,嗐 Python3 中代理使用方法总结

有代理需求是因为漫画堆被墙了,只能整一下了,刚好自己有搭建的v2r,拿谷歌、油管测试没问题,但是用漫画堆的域名总是报错

Failed to establish a new connection: [Errno 11004] getaddrinfo failed'

很郁闷,明明是可以用的,谷歌、油管都正常请求到结果,唯独漫画堆不行,刚好v2r客户端自带显示log 请求谷歌的时候,log为:

accepted tcp:69.63.186.31:443 [proxy] 

请求油管的时候,log为:

accepted tcp:172.217.24.14:443 [proxy] 

但请求漫画堆的时候,log为:

rejected  v2ray.com/core/proxy/socks: failed to read address > EOF

既然能请求到结果的网站都被解析成IP再请求,那漫画堆肯定也是,所以问题应该是出在域名解析上,找了一下解析域名的python代码,使用的下面文章中的代码 python 解析域名,连接主机IP 测试谷歌、油管的域名,得到的IP结果与v2r的log上对应IP是一样的 测试漫画堆时,报错:

socket.gaierror: [Errno 11001] getaddrinfo failed

果然,解析域名的时候出了问题,但是我还是不知道该怎么解决,看了一下上面解析域名的代码,注意到了 gethostbyname(host) 函数,就去查了一下关键词

python  解析域名 gethostbyname 原理

看到了linux下gethostbyname工作原理这篇文章,里面提到

gethostbyname(域名->IP)、gethostbyaddr(IP->域名)在解析的时候,系统默认会先到 /etc/hosts 文件中去寻找匹配信息,然后再到DNS服务器去解析

前面提到的报错信息 [Errno 11001],有一种原因就是请求端与服务器之间有墙,所以我就猜测是因为我连接不上“有漫画堆域名DNS的服务器”,既然没法找DNS服务器解析,那我就先去找在线解析网站找到解析后的漫画堆DNS,将得到的DNS存入host文件

到此为止,漫画堆被墙的问题就解决了

.

总结

要完成功能,那篇知乎文章的源码就能做到,额外需要的修改有:

1、decrypt20180904.js 文件的修改

2、socks5 代理的配置

3、漫画堆的DNS单独写入host文件中