python 爬取整部漫画(简单的图片爬取)

用python爬取整部漫画

契机

最近突然少女心爆棚,追上了一本甜甜的恋爱日漫《寄宿学校的朱丽叶》,可是腾讯坑啊,从第五话就开始收费了

然后就开始在百度上找资源,发现某免费漫画网站好像挺容易爬的,刚好学学爬虫(虽然最后发现好像并没有我想的那么简单,但好歹还是完成了)

一直知道有 requests urllib BeautilfulSoup 这几个库,但是只会用 requests 发个不带参数的 get 请求然后打印内容啥的

因为是学习,为了给自己降低难度,所以只用熟悉一点的官方库 requests,虽然其他两个好像更加方便

收集信息

 目录页

http://comic3.ikkdm.com/comiclist/2160/

网站结构很清晰,comiclist 代表所有漫画的目录,2160 为次漫画,如果要爬取所有漫画,则要控制 2160

按 F12 查看源码
源码
第一个链接是主链接,后面三个是备用链接,备用链接不管,只需要收集两个信息,第一个 href 里的内容,以及中文名称,其中 55245 代表为第一话,因为到了后面就没规律了,所以放弃直接拼接 URL ,而是继续爬出所有链接

这里有两个坑

  • 一个是网页的编码
    涉及到三个编码,一个是 .encoding 返回的 ISO-8859-1,一个是本地默认的 UTF-8,一个是网页的编码 gbk,一开始我以为是应为 UTF-8 显示不正常,把它 decode 为 ISO-8895-1 ,结果更乱了,最后才知道,好像是传过来的是 ISO-8859-1,要 decode 为 gbk 才正常
#所以这两种是可以正常显示中文的
data.content.decode('gbk')
data.text.encode('ISO-8859-1').decode('gbk')  #ISO-8859-1要不要好像都没关系
  • 然后是,F12的内容跟爬取的内容有一点点出入(可能是浏览器做了优化???)
    首先是 href 标签用的是 单引号,浏览器显示的 双引号,还有 a标签,有的是大写,有的是小写
    经测试,下面的正则可以正确得到想要的内容(正则不太会写,有更好的写法,麻烦师傅们不吝赐教)
    两个括号中的内容即所需,其中 1.htm 后面发现为页数,所以不在爬取的范围内
href = re.findall("<[aA] href='(/comiclist/2160/.*?)/1.htm'.*?>(.*?)</[Aa]>", data)

  内容页

点击任一话,按 F12 查看源码
源码
可以看到有一个 img 标签后面有图片地址,一开始我以为就这么简单,但是我还是太年轻了,结果测试的时候发现正则匹配不到
在这里插入图片描述
查看 python 返回的内容(写到这里,我想到Ctrl+U应该是一样的,貌似确实如此),发现并没有那么一句,然后我猜测可能是 JS 代码加载出来的


对比 JS 和下面的地址
<IMG SRC='"+m201304d+"newkuku/2016/06/21/寄宿学校的朱丽叶/001/000150P.jpg
http://s4.kukudm.com/newkuku/2016/06/21/寄宿学校的朱丽叶/001/000150P.jpg

发现是可以通过 JS 代码拼接出图片地址的

但是,奇怪的事情又发生了
正则匹配不到 <IMG SRC=’"+m201304d+ ,我在 notepad 里直接复制都搜索不到它,这是我一直想不通的问题 (我真是太蠢,+ 用 \ 转义便可了)

最后通过如下正则得到图片地址

image = re.search("(newkuku/20.*?)'>", content)

开始爬取

  目录页

首先回到目录页,爬取每一话的链接和名称

import requests
import re

url = 'http://comic3.ikkdm.com/comiclist/2160/'

data = requests.get(url)
data = data.content.decode('gbk')

href = re.findall("<[aA] href='(/comiclist/2160/.*?)/1.htm'.*?>(.*?)</[Aa]>", data)

a = [i[0] for i in href]
b = [i[1] for i in href]

urls = ["http://comic3.ikkdm.com" + link for link in a]
paths = [d for d in b]

print(href)
print(urls)
print(paths)

输出结果,分别得到所有话的链接和名称
在这里插入图片描述

  内容页

既然得到了每一话的链接,那么下一步就是保存图片

先测试其中一话,将图片保存到相应的目录下面,代码如下

import os
import requests
import re

url = 'http://comic3.ikkdm.com/comiclist/2160/52245/1.htm'
path = "朱丽叶"

content = requests.get(url)
content = content.content.decode('gbk')

image = re.search("(newkuku/20.*?)'>", content)  #满足正则的有两个,但是只要第一个,search匹配到就结束,速度应该会比 finfall 快一点
img = 'http://s4.kukudm.com/' + image.group(1)

jpg = requests.get(img)
jpg = jpg.content

os.system('mkdir '+path)
with open(path + '/1.jpg', 'wb') as f:
    f.write(jpg)

成功在脚本的目录下生成了 ”朱丽叶“ 的目录,并保存了一张 1.jpg 的图片

这还不够,我们之前提到最后的 1.htm 表示此话的第一页,这里是有规律的,后面的就链接就很容易想到,写个循环就能解决的

但是到底该循环几次呢??
再去源码里找找
发现这个东西
页码
页眉、页脚都有,正则同样能匹配两次,所以依然用 search,不用 findall
代码如下:

import requests
import re

url = 'http://comic3.ikkdm.com/comiclist/2160/52245/1.htm'

data = requests.get(url)
data = data.content.decode('gbk')

total = re.search('共(\\d+)页', data)

print(int(total.group(1))) #输出50,没有问题,因为是循环用到的,所以把他转化为整型

完整代码

把上面的代码稍作修改、拼接到一起,便可以得到完整代码去爬取漫画了

如下

import re
import time
import requests
import os

url = 'http://comic3.ikkdm.com/comiclist/2160/'
data = requests.get(url)
data = data.text.encode('ISO-8859-1').decode('gbk')

href = re.findall("<[aA] href='(/comiclist/2160/.*?)/1.htm'.*?>(.*?)</[Aa]>", data)

a = [i[0] for i in href]
b = [i[1] for i in href]
urls = ["http://comic3.ikkdm.com" + link for link in a]
paths = [d for d in b]

for i in range(0,len(a)):
    paths[i] = paths[i].replace(" ", "_")
    os.system('mkdir ' + paths[i])

    # url = 'http://comic3.ikkdm.com/comiclist/2160/68767'
    url = urls[i]
    content = requests.get(url + '/1.htm')
   
    if content.status_code == 404:
        print(paths[i]+"--->404")
        continue
        
    content = content.text.encode('ISO-8859-1').decode('gbk')
    total = re.search('共(\\d+)页', content)

    for j in range(1, int(total.group(1)) + 1):
        time.sleep(2)
        host = url + '/' + str(j) + '.htm'
        content = requests.get(host)
        content = content.text.encode('ISO-8859-1').decode('gbk')

        image = re.search("(newkuku/20.*?)'>", content)
        img = 'http://s4.kukudm.com/' + image.group(1)

        jpg = requests.get(img)
        jpg = jpg.content

        with open(paths[i] + '/' + str(j) + '.jpg', 'wb') as f:
            f.write(jpg)

        print("finished %d/%d---->%d/%d" % (int(i),int(len(a)),int(j),int(total.group(1))))

实际测试过程中还是状况百出,所以又加了一点点东西

  • paths[i] = paths[i].replace(" ", “_”)
    中间有个空格,直接给我创建了两个文件夹,所以把空格替换一下
  • 判断是不是 404
    有几话没有,不加这个程序就会报错
  • sleep(2)
    间隔两秒,太快了容易出事
  • 最后加了个进度

记录一下自己所学到的知识,以加深印象

如果这篇文章让你觉得有一点点用,那我都觉得十分荣幸
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值