今天我们来爬取一个漫画网站
这里由于漫画数量过于庞大,于是我就简单地爬取曾经小时候看过的漫画吧。
比如下面的五个漫画:
先来分析分析,拿《火影忍者》举例:
点击进去后可以看到所有的章节罗列。
嗯,这个没啥说的了,就是搜索出所有的< a>元素,找出其章节的标签,并且得到具体章节的链接,这个简单。
继续点击其中某个章节进去后发现,是存在多个页面的插画,共同组成一个章节,这个总体来说也不难,因为url很有规律,url是递增的,直到共X页面,且每一页只有一张图片,我们只需要跳转到每一页下载一张图就行,看着思路可还行。
http://comic.kkkkdm.com/comiclist/3/3/1.htm
http://comic.kkkkdm.com/comiclist/3/3/2.htm
http://comic.kkkkdm.com/comiclist/3/3/3.htm
一直到
http://comic.kkkkdm.com/comiclist/3/3/X.htm
结果,在获取Img的时候获取不到,始终是空的,是None值。
原因是这个img的元素是经过javascript脚本动态添加的,因此我们无法获得其img元素,但是我们也能看到具体嵌入的javascript脚本信息,这里面是产生img的代码,因此我们可以通过解析这个代码字符串的地址来获得具体图片的地址。
可是还是会遇到一个问题就是,这个字符串的地址信息包含一个变量,而且经过信息打印,发现一共包含多个不同名称的变量,那么这个变量值是多少呢?
由于它们是javascript的变量值,因此我们就在本页面找所有的javascript文件,从中去找。
终于在本页中找到了一个js文件如下:
打开后能看到
这下全部就清晰了,其实那么多变量的值都是指向了同一个地址。好了这下问题全部清楚了,
讲真的幸亏自己曾经大学时候自学过一些简单的HTML / CSS / JavaScript的知识,不然的话就无法完成漫画下载了。
我们来找一个图片来试试水。
测试代码如下:
Import requests
def run11():
with open("D:/estimages/mn.jpg", "wb") as f :
f.write(requests.get("https://v2.kukudm.com/kuku6comic6/200910/20091010/glgs/Vol_01/cccc.rar 00003A.jpg").content)
f.close
if __name__ == "__main__": #主程序入口
run11() #调用上面的run方法
效果还行,那么接下来我们上完整代码:
# coding: utf-8
from concurrent.futures import ThreadPoolExecutor
import time
import os
import requests
from bs4 import BeautifulSoup
rootrurl = 'http://comic.kkkkdm.com'
server_url = 'https://v2.kukudm.com/'
save_dir = 'D:/estimages/'
headers = {
"Referer": rootrurl,
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive'
} ###设置请求的头部,伪装成浏览器
def saveOneCapCore(dir, img_url):
img = requests.get(img_url) # 请求图片的实际URL
with open(
'{}/{}'.format(dir, img.url.split("/")[-1]), 'wb') as jpg: # 请求图片并写进去到本地文件
jpg.write(img.content)
print(img_url)
# 从 script 元素里面获得出图片的链接地址
def parseImgUrl(info):
tmp = info.split('+')[2]
return server_url + tmp[tmp.find('"') + 1: tmp.find("'")]
def saveOneCap(dir, href):
# 找到共有多少页?
html = BeautifulSoup(requests.get(href, headers=headers).text.encode('iso-8859-1').decode('gbk'),
features="html.parser")
tbl = html.find_all('table')[1]
info = tbl.find('td')
totalPages = int(info.get_text().split('|')[1].strip()[1:-1])
tmpurl = href[: href.find(href.split('/')[-1])]
for i in range(1, (totalPages + 1)):
url = '{}{}.htm'.format(tmpurl, i)
print(url)
html = BeautifulSoup(requests.get(url, headers=headers).text.encode('iso-8859-1').decode('gbk'),
features="html.parser")
tbl = html.find_all('table')[1]
info = tbl.find('td').find('script').string
# saveOneCapCore(dir, html.find('img', {"id" : "comicpic"}).get('src')) # 动态生成的,无法直接获得img的地址
saveOneCapCore(dir, parseImgUrl(info)) # img的地址是动态生成,因此需要从javascript中解析出来
def saveOnePageFunc(dir, capters):
for cap in capters:
# 按照tag和图片组的内容来创建目录
new_dir = '{}{}/{}'.format(save_dir, dir, cap.get_text())
if not os.path.exists(new_dir):
os.makedirs(new_dir)
saveOneCap(new_dir, rootrurl + cap.get('href'))
pass
def tagSpider(tag, url):
# 解析当前页面
html = BeautifulSoup(requests.get(url, headers=headers).text.encode('iso-8859-1').decode('gbk'),
features="html.parser")
# 提交一个保存页面的任务
saveOnePageFunc(tag, html.find('dl', {'id': 'comiclistn'}).find_all('a')[::4])
print("thread work over. ")
if __name__ == '__main__':
# 获得所有标签
taglist = {'火影忍者': 'http://comic.kkkkdm.com/comiclist/3/',
'犬夜叉': 'http://comic.kkkkdm.com/comiclist/833/',
'灌篮高手': 'http://comic.kkkkdm.com/comiclist/34/',
'网球王子': 'http://comic.kkkkdm.com/comiclist/720/',
'通灵王': 'http://comic.kkkkdm.com/comiclist/163/'}
# 给每个标签配备一个线程
with ThreadPoolExecutor(max_workers=10) as t: # 创建一个最大容纳数量为20的线程池
for tag, url in taglist.items():
t.submit(tagSpider, tag, url)
# 等待所有线程都完成。
while 1:
time.sleep(1)
效果如下: