漫画网站一般都是通过JavaScript和AJAX来动态加载漫画的,这也就意味着想通过原来爬取静态网站的方式去下载漫画是不可能的,这次我们就来用Selenium&PhantomJS来下载漫画。
目标分析:
这次我们要爬的漫画网站是:http://comic.sfacg.com/
资源丰富,更新频率也还不错~
目标依旧很明确:
通过Selenium模拟打开漫画网站,
找到每一章每一页的漫画的图片地址,
按章节目录分类并下载该图片。
数据筛选:
随便找一个漫画点进去看看:
我们仔细研究一下,发现每一章漫画的链接都包含在
里:
这样事情就简单多了,我们用任何一种数据筛选的方式,都能够快速的找到漫画章节的地址。
代码的编写:
还是按照模块化的编写方式,
目录创建和图片保存:
这里很简单,没什么好说的,直接看代码和注释就成
def mkdir(path):
'''防止目录存在'''
if not os.path.exists(path):
os.mkdir(path)
def SavePic(filename, url):
'''通过requests库将抓取到的图片保存到本地'''
content = requests.get(url).content
with open(filename, 'wb') as f:
f.write(content)
漫画章节目录的获取:
这里就按照我们一开始的分析,找到漫画章节的地址就行
为了方便下载图片的时候能将图片放在正确的章节文件夹里,这里的得传回去漫画的title,
当然,这样做是不好的
这使得程序的每一个部分联系的太紧了。用程序员的话就是:高耦合
可是一想,定站爬虫这种东西,网站结构一变,那肯定就是不能用了,
关键部分肯定还是要手动更新,维护什么的就相当于重写一遍核心程序。所以我就放纵了一把 (逃~
def get_TOF(index_url):
'''获取漫画的目录中的每一章节的url连接并返回一个字典类型k:漫画名 v:章节链接'''
url_list = []
# 模拟浏览器并打开网页
browser = webdriver.PhantomJS()
browser.get(index_url)
browser.implicitly_wait(3)
# 找到漫画标题 并创建目录
title = browser.title.split(',')[0]
mkdir(title)
# 找到漫画章节,注意,漫画可能会有多种篇章
# 例如番外,正文,短片等等
comics_lists = browser.find_elements_by_class_name('comic_Serial_list')
# 寻找、正文等
for part in comics_lists:
# 找到包裹链接的links
links = part.find_elements_by_tag_name('a')
# 找到每个单独的章节链接
for link in links:
url_list.append(link.get_attribute('href'))
# 关闭浏览器
browser.quit()
Comics = dict(name=title, urls=url_list)
return Comics
图片地址:
这个部分是整个爬虫的核心,
具体的思路就是:
通过Selenium打开漫画
找到漫画的真实地址:
调用图片下载函数,下载漫画
找到漫画中的 下一页 按钮,点击它获取下一张图片
循环这个过程
但是在实现的过程中,我发现,
就算到了漫画的最后一页,
还是会有下一页这个按钮,
所以需要我们自己计算一下漫画有多少页
方法也很简单,相信看了注释你一定能明白的:
def get_pic(Comics):
'''打开每个章节的url,找到漫画图片的地址,并写入到本地'''
comic_list = Comics['urls']
basedir = Comics['name']
browser = webdriver.PhantomJS()
for url in comic_list:
browser.get(url)
browser.implicitly_wait(3)
# 创建章节目录
dirname = basedir + '/' + browser.title.split('-')[1]
mkdir(dirname)
# 找到该漫画一共有多少页
pageNum = len(browser.find_elements_by_tag_name('option'))
# 找到下一页的按钮
nextpage = browser.find_element_by_xpath('//*[@id="AD_j1"]/div/a[4]')
# 找到图片地址,并点击下一页
for i in range(pageNum):
pic_url = browser.find_element_by_id('curPic').get_attribute('src')
filename = dirname + '/' + str(i) + '.png'
SavePic(filename, pic_url)
# 点击下一页的按钮,加载下一张图
nextpage.click()
print('当前章节\t{} 下载完毕'.format(browser.title))
browser.quit()
print('所有章节下载完毕')
Mian函数:
这里就是让项目跑起来的入口了,没啥好说的:
def main():
url = str(input('请输入漫画首页地址:\n'))
Comics = get_TOF(url)
get_pic(Comics)
if __name__ == '__main__':
main()
结果的展示:
粗略的计算了一下,
爬取一个30章的漫画需要5分钟左右
可以看到,漫画都按照目录乖乖的下载好了:
点开一个文件夹:
Selenium爬虫虽然能模拟浏览器加载JS动态页面,
但是其速度就十分堪忧了
和Scrapy库、requests更完全不能比了。
怎么说呢,有得必有失吧!
我也尝试写了一个多线程的版本,可是被封ip啦~代码我放在GitHub上了,有兴趣的小伙伴可以接手开发一下。
到这里
从零开始写Python爬虫系列就完结了,
没想到当时的冲动居然真的坚持到了最后
当然,这个专栏并不会停止更新的,
还是会时不时的发一些我写的小爬虫程序上来,
同时也希望喜欢写爬虫的小伙伴来投稿呀~
Bye~
每天的学习记录都会 同步更新到:
微信公众号: findyourownway
知乎专栏:从零开始写Python爬虫 - 知乎专栏
blog : www.ehcoblog.ml
Github: Ehco1996/Python-crawler