关于用python爬虫白嫖漫画这档子事

文章目录

关于用python爬虫白嫖漫画这档子事前言操作环境网页分析1. 漫画主页2. 获取章节链接列表3. 获取章节图片4. 小结

编写代码1. 准备2. 获取章节链接列表3. 获取图片列表4. 图片下载

运行完整代码

前言

笔者平时喜欢看漫画,用得比较多的漫画APP是txdm和kkmh,尽管都开了会员,靠着平时做任务和签到得到的点卷凑活度日,但依旧无法满足,尤其是发现一些完结的神作,整本下来也得几百,对于一个学生来说,还是很肉疼的,于是萌生用爬虫来白嫖的想法。

网上教程很多,也包括爬取txdm的,但它是无法爬取付费部分的,除非买下付费部分,这就与我的初衷背道相驰了。所以我的目标只能转向同样是爬虫爬来的漫画网站,这些网站有几个共同点:广告多,阅读体验差,一般坚持不了一年就没了。 现在是2022年11月,我找到的一个几乎无反爬,下载速度快的漫画网站m.imitui.com,如果你看到这篇文章时,这个链接是无效的,或者在这个网站上没有找到你想看的漫画,也没必要往下看了。

操作环境

Python: 3.8

第三方库:requests, selenium

网页分析

1. 漫画主页

搜索漫画名,进入漫画主页,观察导航栏URL,可以发现是有规律的,即weburl+comic_name,这里comic_name作为参数传给程序看到以下折叠章节列表

2. 获取章节链接列表

按F12,检查章节元素

右键点击元素,复制选项里得到xpath路径为://*[@id="chapter-list-1"]/li[2]/a,即所有的章节链接统一表示为//*[@id="chapter-list-1"]/li/a章节链接地址就在的href属性中。

3. 获取章节图片

进入任意一个章节,检查图片元素,发现分为两部分:封面和内容封面图片如下,右击,在复制选项中得到对象xpath路径://*[@id="image"]

内容图片如下,右击,在复制选项中得到对象xpath://*[@id="scroll-item-1"]/img

图片的url就在的src属性中。

4. 小结

总体思路:漫画页面->章节链接列表->进入章节下载图片注意:需要在请求头header中加入refer,表明请求来自于哪儿

编写代码

1. 准备

import sys

import time

import requests

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

import os

import threading

# 漫画在本地的存储路径,%s用来替换文件夹名

DIRBASE = 'D:/Picture/Comics/%s/'

# 无需启动浏览器UI运行

chromeOptions = Options()

chromeOptions.add_argument('--headless')

# 请求头

HEADER = {

'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '

'Chrome/107.0.0.0 Safari/537.36',

'Referer': 'https://m.imitui.com/'

}

def main(comic_name, dir_name, restart=0):

"""

:param comic_name: 从漫画主页的url中提取的漫画名

:param dir_name: 自己命名的存储文件夹

:param restart: 各种原因导致程序结束,可以设置重启的章节数

"""

# 创建存储文件夹

global DIR, URL

DIR = DIRBASE % dir_name

if not os.path.exists(DIR):

os.mkdir(DIR)

# 需要爬取的漫画主页url

URL = 'https://m.imitui.com/manhua/%s' % comic_name

# 爬取正式开始

run(restart)

if __name__ == '__main__':

# 在命令行中这样调用 python crawler.py comic_name dir_name

# 若中断过,则这样: python crawler.py comic_name dir_name restart

arg1 = sys.argv[1]

arg2 = sys.argv[2]

if len(sys.argv) > 3:

arg3 = sys.argv[3]

main(arg1, arg2, int(arg3))

else:

main(arg1, arg2)

2. 获取章节链接列表

def run(restart):

# 1. 初始化浏览器驱动

driver = webdriver.Chrome(options=chromeOptions)

# 2. 获取章节列表

driver.get(URL)

time.sleep(2)

chapter_list = driver.find_elements('xpath', '//*[@id="chapter-list-1"]/li/a')

# 除去预告

chapter_list.pop()

# 逆序,从低序号章节开始

chapter_list.reverse()

# 3. 访问章节页面进行操作

for j in range(restart, len(chapter_list)):

# 进入对应章节页面

print('进入章节%d: ' % j + chapter_list[j].get_attribute('href'))

# 创建章节文件夹

directory = DIR + '%03d/' % j

if os.path.exists(directory):

continue

os.mkdir(DIR + '%03d/' % j)

# 开始下载章节

get_chapter(DIR + '%03d/' % j, chapter_list[j].get_attribute('href'))

# time.sleep(1)

# 6. 退出

driver.quit()

3. 获取图片列表

def get_chapter(directory, url):

# 1. 初始化浏览器驱动

driver = webdriver.Chrome(options=chromeOptions)

# 2. 访问章节页面

driver.get(url)

# 3. 提取内容图片列表

img_list = driver.find_elements('xpath', '//*[@id="scroll-image"]/div/img')

# 4. 插入封面图片

img_list.insert(0, driver.find_element('xpath', '//*[@id="image"]'))

# 这里采用多线程下载,即将一个章节的图片分成三份下载

pos14 = int(len(img_list)/4)

pos24 = int(len(img_list)/4*2)

pos34 = int(len(img_list)/4*3)

# ImageDownloader类的实现在后面

# 其他线程

thread1 = ImageDownloader(img_list, directory, pos14, pos24)

thread2 = ImageDownloader(img_list, directory, pos24, pos34)

thread3 = ImageDownloader(img_list, directory, pos34, len(img_list))

thread1.start()

thread2.start()

thread3.start()

# 主线程

getImage(img_list, directory, 0, pos14)

4. 图片下载

class ImageDownloader(threading.Thread):

"""

下载图片的线程类

"""

def __init__(self, img_list, directory, start, end):

self.img_list = img_list

self.directory = directory

self.begin = start

self.end = end

super().__init__()

def run(self):

getImage(self.img_list, self.directory, self.begin, self.end)

def getImage(img_list, directory, start, end):

for i in range(start, end):

# 4.1 获取图片url

img_url = img_list[i].get_attribute('data-src')

if img_url is None:

img_url = img_list[i].get_attribute('src')

# 4.2 发送请求,获取数据

img_data = requests.get(img_url, headers=HEADER).content

# 4.3 保存数据

with open('%s%03d.jpg' % (directory, i), mode='wb') as image:

image.write(img_data)

运行

在当前项目文件夹中:python .\IMIComic.py nitianxieshen xieshen

完整代码

import sys

import time

import requests

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

import os

import threading

DIRBASE = 'D:/Picture/Comics/%s/'

chromeOptions = Options()

chromeOptions.add_argument('--headless')

HEADER = {

'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '

'Chrome/107.0.0.0 Safari/537.36',

'Referer': 'https://m.imitui.com/'

}

DIR = ''

URL = ''

def main(comic_name, dir_name, restart=0):

"""

:param comic_name: 从漫画主页的url中提取的漫画名

:param dir_name: 自己命名的存储文件夹

:param restart: 各种原因导致程序结束,可以设置重启的章节数

"""

global DIR, URL

DIR = DIRBASE % dir_name

if not os.path.exists(DIR):

os.mkdir(DIR)

URL = 'https://m.imitui.com/manhua/%s' % comic_name

run(restart)

def run(restart):

# 1. 初始化浏览器驱动

driver = webdriver.Chrome(options=chromeOptions)

# 2. 获取章节列表

driver.get(URL)

time.sleep(2)

chapter_list = driver.find_elements('xpath', '//*[@id="chapter-list-1"]/li/a')

chapter_list.pop()

chapter_list.reverse()

# 3. 访问章节页面进行操作

for j in range(restart, len(chapter_list)):

# 进入对应章节页面

print('进入章节%d: ' % j + chapter_list[j].get_attribute('href'))

directory = DIR + '%03d/' % j

if os.path.exists(directory):

continue

os.mkdir(DIR + '%03d/' % j)

get_chapter(DIR + '%03d/' % j, chapter_list[j].get_attribute('href'))

# time.sleep(1)

# 6. 退出

driver.quit()

def get_chapter(directory, url):

# 1. 初始化浏览器驱动

driver = webdriver.Chrome(options=chromeOptions)

# 2. 访问章节页面

driver.get(url)

# 3. 提取图片列表

img_list = driver.find_elements('xpath', '//*[@id="scroll-image"]/div/img')

img_list.insert(0, driver.find_element('xpath', '//*[@id="image"]'))

pos14 = int(len(img_list)/4)

pos24 = int(len(img_list)/4*2)

pos34 = int(len(img_list)/4*3)

thread1 = ImageDownloader(img_list, directory, pos14, pos24)

thread2 = ImageDownloader(img_list, directory, pos24, pos34)

thread3 = ImageDownloader(img_list, directory, pos34, len(img_list))

thread1.start()

thread2.start()

thread3.start()

getImage(img_list, directory, 0, pos14)

class ImageDownloader(threading.Thread):

"""

下载图片的线程类

"""

def __init__(self, img_list, directory, start, end):

self.img_list = img_list

self.directory = directory

self.begin = start

self.end = end

super().__init__()

def run(self):

getImage(self.img_list, self.directory, self.begin, self.end)

def getImage(img_list, directory, start, end):

for i in range(start, end):

# 4.1 获取图片url

img_url = img_list[i].get_attribute('data-src')

if img_url is None:

img_url = img_list[i].get_attribute('src')

# 4.2 发送请求,获取数据

img_data = requests.get(img_url, headers=HEADER).content

# 4.3 保存数据

with open('%s%03d.jpg' % (directory, i), mode='wb') as image:

image.write(img_data)

if __name__ == '__main__':

arg1 = sys.argv[1]

arg2 = sys.argv[2]

if len(sys.argv) > 3:

arg3 = sys.argv[3]

main(arg1, arg2, int(arg3))

else:

main(arg1, arg2)

推荐阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: