漫画屋 - 爬取所有漫画(js解析-只要有就能获取)
JS解析网站大体流程(自我感觉一般都是这个流程)
- 网站踩点 ----- 先去查看这个网站数据加载的一种方式或者说网站加载的流程
- 接口分析 ----- 找到数据接口分析出必要的加密参数
- 加密算法 ----- 通过加密的参数找到加密算法的JS代码
- 伪造请求 ----- JS简单的话可以翻译成python代码,如果复杂可以使用nodejs、execjs等去进行调用
- 获取数据 ----- 可以进一步的进行数据清洗以及后期扩展
1. 解析网站
要进行爬取的网站:http://www.dm5.com/manhua-list-p1/
-
我们先看看全部漫画,它的漫画封面 漫画名字是怎么请求的以及翻页
-
既然找到漫画封面加载方式那么就点开一个漫画看看,这种连载章名是可以直接获取出来的
-
那就打开章节漫画看看里面的漫画是如何加载的
- 但多点击几页发现一直会请求这两个数据包 每一个都返回了这个eval函数, 这一点有些不同
- 把这段js代码放到控制台 此时我们就找到了这个图片的URL存储地址
- 既然找到了图片的加载方式,那就看看它是怎么进行获取的
7. 那我们继续搜索DM5_VIEWSIGN这个参数最后发现这个参数是在源码中 既然这个参数在源码中那么其他的参数也应该是在源码中了 现在我们找到了所有的参数那么我们就可以进行伪造请求获取数据了
2. 代码实现
代码分析流程:获取漫画名字以及漫画详情的URL并创建漫画文件夹 ----- 获取漫画详情章节并创建章节文件夹 ----- 获取图片URL取出js代码片段 ----- 调用js代码获取图片链接 ----- 进行下载保存漫画图片
使用模块:os、re、execjs、requests、BeautifulSoup
import os
import re
import execjs
import requests
from bs4 import BeautifulSoup as bs
HOST = 'http://www.dm5.com'
ROOT = '漫画'
def safe_string(str):
"""去除特殊符号"""
return re.sub('[:,.\'@#$%……¥&*~`]', '_', str)
def get_index():
"""获取所有漫画的URL"""
page = 1
while 1:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"}
api_url = 'http://www.dm5.com/dm5.ashx?'
data = {
'pagesize': 68,
'pageindex': page,
'tagid': 0,
'areaid': 0,
'status': 0,
'usergroup': 0,
'pay': -1,
'char': '',
'sort': 10,
'action': 'getclasscomics'
}
response = requests.post(api_url, data, headers=headers)
reult = response.json()
Update_items = reult['UpdateComicItems']
if not Update_items:
pass
for x in Update_items:
comic_name = x['Title']
comic_url = HOST +'/' + x['UrlKey']
try:
detail_comic(comic_name, comic_url)
except Exception as e:
print(comic_name, '>章节调整中')
page += 1
def detail_comic(comic_name, comic_url):
"""获取漫画章节"""
_path_one = os.sep.join([ROOT, safe_string(comic_name)])
if not os.path.exists(_path_one):
os.makedirs(_path_one)
print(f'漫画:<{comic_name}> 正在下载中')
response = requests.get(comic_url)
dom = bs(response.text, 'lxml')
div = dom('div', id='chapterlistload')[0]
li_list = div.ul('li')
for li in li_list:
chapter_url = HOST + li.a['href']
chapter_name = re.sub('[ ]', '', li.text)
# print(chapter_url, chapter_name)
try:
parse_chapter(chapter_url, chapter_name, _path_one)
except Exception as e:
print(f"章节<{chapter_name}>下载错误,{e}")
def parse_chapter(chapter_url, chapter_name, _path_one):
"""解析漫画"""
_path_two = os.sep.join([_path_one, chapter_name])
if not os.path.exists(_path_two):
os.makedirs(_path_two)
# 获取漫画的必要参数
response = requests.get(chapter_url)
text = response.text
cid = re.findall('var DM5_CID=(.*?);', text)[0].strip()
mid = re.findall('var DM5_MID=(.*?);', text)[0].strip()
dt = re.findall('var DM5_VIEWSIGN_DT="(.*?)";', text)[0].strip()
sign = re.findall('var DM5_VIEWSIGN="(.*?)";', text)[0].strip()
page_count = int(re.findall('var DM5_IMAGE_COUNT=(.*?);', text)[0].strip())
# print(cid, mid, dt, sign, page_count)
page = 1
while page <= page_count:
js_api = f'{chapter_url}chapterfun.ashx?cid={cid}&page={page}&key=&language=1>k=6&_cid={cid}&_mid={mid}&_dt={dt}&_sign={sign}'
headers = {
'referer': HOST
}
ret = requests.get(js_api, headers=headers)
js_code = ret.text
print(js_code)
image_url = execjs.eval(js_code)
img_url = image_url[0]
img_name = chapter_name + str(page)
try:
download_image(img_url, img_name, _path_two)
except Exception as e:
print(f'章节<{chapter_name}>图片{img_name}下载失败:{e}')
page += 1
def download_image(img_url, img_name, _path_two):
"""下载漫画图片"""
save_path = os.sep.join([_path_two, img_name])
if os.path.exists(save_path):
return
response = requests.get(img_url)
with open(save_path+'.jpg', 'wb') as f:
f.write(response.content)
print(f'{img_name}, 下载成功')
if __name__ == '__main__':
get_index()