本文皆以《第一话上》为例
目标网站:知音漫客(请点击这里)
目标漫画:元尊(请点击这里)
链接失效就自己上网搜吧~
最后有详细代码和解释
import requests
from bs4 import BeautifulSoup
import os
class downloader(object): # 定义全局变量
def __init__(self):
self.url = 'https://www.zymk.cn/1966/'
self.list_names = []
self.list_urls = []
# 提取目录
def get_name_url(self):
req = requests.get(url=self.url)
req.encoding = req.apparent_encoding
reqhtml = BeautifulSoup(req.text, features='lxml')
reqhtml = reqhtml.find_all('ul', class_='chapter-list clearfix') # 相当于正则表达式的效果
bf = BeautifulSoup(str(reqhtml), features='lxml')
a = bf.find_all('a')
for one in a[::-1]: # 结果是倒序的,要顺序的
self.list_names.append(one.string)
self.list_urls.append(self.url + one.get('href'))
return self.list_urls, self.list_names
if __name__ == '__main__':
down = downloader()
down.get_name_url()
可以点击上面我们找到的URL,验证我们是否正确。
以第一话漫画为例:
这时我很高兴,我以为我找到了我想要的URL,获取该网页的源码:
import requests
from bs4 import BeautifulSoup
import os
import json
req = requests.get(url='https://www.kanman.com/105855/1hs.html')
print(req.text)
代码部分截图:
我们用Element里的图片URL和代码获取网页源码的图片URL是对应不上的,也访问不了,直接显示403,加上headers和from data也不行,这说明了我们要的内容URL不在这里。没有在HTML里找到的图片URL,那么它应该是动态加载的。
在Network
里找:
接下来是体力活了,只能一个个找,也不知道哪个才是我们想要的,最终我们锁定这个文件,它让我们看到了熟悉的东西,也可以实现访问,返回图片,这就是我们想要的:
就找第一张图片的URL去验证一下:
状态码:200,说明返回联通。现在我们找到了真正的URL:
URL里"?"
之后的都是参数,给服务器检索信息等用的,这些参数可以在General这列最后可以找到:
观察多章漫画URL发现规律:只有“chapter_newid”
这个参数是变化的,其它均不变,这个参数也正好对应“第几话”。这里有个陷阱,这部漫画的每一话又分上下话,特别到了后面的付费章节(可以爬付费章节,这我也没想到,居然没做反爬……
),id更是千奇百怪,这是踩坑的经验,所以要拿到“chapter_newid”这个参数,我们只能回到Element
那里寻找,也可以requests请求返回的content
里找:
然后把这些章节的id抠出来替换URL里的就得到了每一话的漫画URL了。
import requests
from bs4 import BeautifulSoup
import os
import json
import pprint
req = requests.get(url='https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id=105855&chapter_newid=1hs&isWebp=1&quality=middle')
pprint.pprint(req.json()) # json文件格式化输出
json_data = req.json()
pic_url = json_data["data"]["current_chapter"]["chapter_img_list"] # 提得每话漫画里的每张图片url
name = json_data["data"]["current_chapter"]["chapter_name"] # 提得每话漫画的题目
print(pic_url)
print(name)
如果不知道json文件的定义和怎么提取它里面的数据,自己找一下吧。
这样子我们就可以直接从请求图片url保存图片。
for循环就可以了,具体看后面详细代码。值得注意的是图片格式不是常用的.jpg和.png等等,是.webp。这有点坑……
import requests # 请求url用的
from bs4 import BeautifulSoup # 提取信息用的
import os # 文件操作用的
import json
import pprint # json文件格式化输出用的库
class downloader(object): # 定义全局变量
def __init__(self):
self.url = 'https://www.zymk.cn/1966/'
self.unique = 1 # 防止文件名重复,作为序号使用,每次+1
self.i = 0 # 遍历章节题目用的
self.list_names = [] # 所有章节题目
self.list_urls = [] # 所有章节url
self.true_urls = [] # 所有章节真正的url
# 提取目录
def get_name_url(self):
req = requests.get(url=self.url)
req.encoding = req.apparent_encoding # 解决返回网页乱码问题
reqhtml = BeautifulSoup(req.text, features='lxml')
reqhtml = reqhtml.find_all('ul', class_='chapter-list clearfix') # 定位章节url位置
bf = BeautifulSoup(str(reqhtml), features='lxml')
a = bf.find_all('a') # 精确提取章节url
for one in a[::-1]: # 章节目录是倒序的,要顺序的
self.list_names.append(one.string) # 添加到名字列表里去
self.list_urls.append(self.url + one.get('href')) # 添加url
# print(self.list_urls)
# print(self.list_names)
print("已完成目录提取")
return self.list_urls, self.list_names
# 获取内容
def get_content(self):
filename = '元尊'
os.mkdir(filename) # 创建父目录
print("已完成父目录创建")
for net in self.list_urls: # 遍历章节url
requrl = requests.get(url=net)
requrl.encoding = requrl.apparent_encoding
reqhtml = BeautifulSoup(requrl.text, features='lxml')
reqhtml = reqhtml.find_all('link', rel='prefetch prerender') # 提取章节id,chapter_newid
# print(str(str(reqhtml).replace('[]', ''))
self.true_urls.append('https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id=105855&'+'chapter_newid='+str(str(reqhtml).replace('[, '')).replace('.html" rel="prefetch prerender"/>]', '')+'&isWebp=1&quality=middle') # 这才是真正的章节url
print("已完成{}真正的图片URL爬取".format(self.list_names[self.i]))
self.i += 1
print("已完成真正的漫画图片目录提取")
for url in self.true_urls: # 遍历真正的url,开始保存图片
n = 1
if requests.get(url=url).status_code == 200: # 状态码200避免不必要的错误导致程序停止
req = requests.get(url=url)
json_data = req.json() # json文件加载
pic_url = json_data["data"]["current_chapter"]["chapter_img_list"] # 提取图片url
name = json_data["data"]["current_chapter"]["chapter_name"] # 提取图片名字
if os.path.exists(filename + '/' + name): # 防止文件名重复
dirname = filename + '/' + name + 'self.unique'
os.mkdir(dirname)
self.unique += 1
else:
dirname = filename + '/' + name
os.mkdir(dirname)
for pic in pic_url: # 保存图片
n += 1
with open(dirname + '/' + str(n) + '.webp', 'wb') as file: # 特别注意图片格式
file.write(requests.get(url=pic).content)
print("已完成{}爬取".format(name))
else:
print("第{}话爬取失败".format(name))
continue
if __name__ == '__main__':
down = downloader()
down.get_name_url()
down.get_content()