前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >宅男宅女福利!用python爬取网站漫画:“只要本站有的,你们随便看”!

宅男宅女福利!用python爬取网站漫画:“只要本站有的,你们随便看”!

作者头像
Python与Excel之交
发布2021-08-05 15:30:34
3K0
发布2021-08-05 15:30:34
举报
文章被收录于专栏:Python与Excel之交

Hi~ 大家好!

今日教大家用Python爬取某网站的全部漫画,让你想看什么漫画就看什么漫画!本文代码量有的多,请耐心看完!如果不想看分析网页,可拉取到爬取思路实现代码区域,查看基本思路和代码!经过作者测试,测试过的漫画都可以下载!本文图片以及文本仅供学习、交流使用,要想获得更好的体验,请支持正版!

本文完整代码见文末!

分析网页

受害者:

代码语言:javascript
复制
https://www.kanman.com/sort/

漫画其实是一张一张图片来着,所以我们先找到这些图片的链接在哪里!因为本文是为了实现想看什么漫画就爬取什么漫画,所以搜索任一漫画,这里以神印王座为例,然后点进去进入详情页查看任一话;在浏览页中,网页源代码是没有我们需要的数据,所以需要打开开发者工具进行抓包,最终成功找到图片的链接。

找到图片链接后,接着就要想办法从该数据包中获取,也就是访问该数据包的链接,从数据包中提取图片链接。通过多页的数据包,观察以下数据包链接,发现chapter_newid每次翻页会发生变化的,comic_id是一本漫画的唯一标识。

代码语言:javascript
复制
https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id=5323&chapter_newid=1006&isWebp=1&quality=middle
https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id=5323&chapter_newid=2003&isWebp=1&quality=middle
https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id=5323&chapter_newid=3004&isWebp=1&quality=middle

接着查找这两个参数是从哪里来的。进入首页搜索神印王座,接着查看网页源代码,发现可以在网页源代码中找到进入漫画详情页的url;我试着用正则表达式和xpath语法进行提取时,发现困难重重,源代码中的HTML标签有很多的都相同的,且发现源代码中不止一本漫画。

接着我试着搜索其它漫画,发现源代码中没有,我才发现我掉坑里,后来发现该源代码是网站首页的源代码,大意了,泪目!但没关系,源代码中没有,我们去抓包。

打开开发者工具,进入Network中的XHR,搜索神印王座,第一次搜索的时候抓到一条数据包,不过他报红了:

但里面是有我们需要的内容的。不过因为报红,我们在开发者工具中是无法看到数据的,得点开数据包:

如果需要获取不报红的数据包,需要重新点击一下输入框,他就会加载出来了,如果只刷新网页和重新点击搜索他都是无法获取到的。

拿到数据包后,我们找到漫画的唯一标识comic_id,只需要该数据包中提取出来:

找到comic_id后,接着找chapter_newidchapter_newid变化规律每本漫画他都是不同的;但如果你第一次搜索的是斗罗大陆,你会发现,chapter_newid他是递增式变化的。

chapter_newid怎么找呢,进入到漫画的详情页,前面我们知道神印王座的第一话的chapter_newid1006,那我们直接在开发者工具中搜索1006,最终在详情页源代码中找到:

那么我们知道,首个chapter_newid是详情页静态加载来的,可以在详情页的源代码中提取出来,而该网址是https://www.kanman.com/+comic_id构成的:

这里只要第一话的chapter_newid,那其它的从哪里得到呢?经过我的查找,发现后一页的chapter_newid是在前一页中获取到的:

爬取思路

  • 从首页搜索漫画名称,抓包包含漫画信息的数据包,从中提取漫画的唯一标识comic_id
  • https://www.kanman.com/+comic_id拼接成漫画详情页链接,从详情页的源代码中提取漫画第一话的chapter_newid
  • 通过漫画的唯一标识comic_id和漫画第一话的chapter_newid以及包含漫画图片数据的链接拼接成漫画第一话的真实url,从中提取漫画图片的链接。
  • 通过漫画第一话的真实url提取漫画第二话的chapter_newid,从而进行翻页操作。
  • 保存图片数据。
  • 把图片拼接成长图(非必需)

代码实现

构建提取comic_idchapter_id函数:

代码语言:javascript
复制
def get_comic(url):
    data = get_response(url).json()['data']
    for i in data:
        comic_id = i['comic_id']
        chapter_newid_url = f'https://www.kanman.com/{comic_id}/'
        chapter_newid_html = get_response(chapter_newid_url).text
        chapter_id = re.findall('{"chapter_id":"(.*?)"}', chapter_newid_html)
        data_html(comic_id, chapter_id[0])

关键代码,如果以前爬取过微博评论数据的,就会发现,二者的套路差不多,翻页的数值都需要从前一页中获取:

代码语言:javascript
复制
def data_html(comic_id, chapter_id):
    try:
        a = 1
        while True:    # 循环获取chapter_id
            if a == 1:
                comic_url = f'https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id={comic_id}&chapter_newid={chapter_id}&isWebp=1&quality=middle'
            else:
                comic_url = f'https://www.kanman.com/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id={comic_id}&chapter_newid={chapter_newid}&isWebp=1&quality=middle'
            comic_htmls = get_response(comic_url).text
            comic_html_jsons = json.loads(comic_htmls)
            if a == 1:
                chapter_newid = jsonpath.jsonpath(comic_html_jsons, '$..chapter_newid')[1]
            else:    # 自第二条url开始,提取规则+1
                chapter_newid = jsonpath.jsonpath(comic_html_jsons, '$..chapter_newid')[2]
            current_chapter = jsonpath.jsonpath(comic_html_jsons, '$..current_chapter')
            for img_and_name in current_chapter:
                image_url = jsonpath.jsonpath(img_and_name, '$..chapter_img_list')[0]    # 图片url
                # chapter_name 中存在空格,所以需要用strip去除
                chapter_name = jsonpath.jsonpath(img_and_name, '$..chapter_name')[0].strip()
                save(image_url, chapter_name)
            a += 1
    except IndexError:
        pass

保存数据:

代码语言:javascript
复制
def save(image_url, chapter_name):
    for link_url in image_url:    # 图片名称
        image_name = ''.join(re.findall('/(\d+.jpg)-kmh', str(link_url)))
        image_path = data_path + chapter_name
        if not os.path.exists(image_path):    # 创建章节标题文件夹
            os.mkdir(image_path)
        image_content = get_response(link_url).content
        filename = '{}/{}'.format(image_path, image_name)
        with open(filename, mode='wb') as f:
            f.write(image_content)
            print(image_name)
    get_img(chapter_name)    # 拼接函数章节标题,非必需

拼接图片,非必需。下面程序更改图片地址就可以直接使用。这个程序会按章节图片生成一张长图,但生成的图片有的过长了,且图片内存很大。我有另外一条程序,可以把过长的图片分为两张进行保存,这里不在贴出,感兴趣的小伙伴,可以在公众号后台发送“漫画”二字获取!

代码语言:javascript
复制
def get_img(chapter_name):
    image_path = data_path + chapter_name + '/'  # 图片地址
    save_path = '{}/{}.jpg'.format(data_path, chapter_name)  # 图片转换后输出地址

    # 获取图片地址下的所有图片
    image_names = [name for name in os.listdir(image_path) for item in ['.jpg', '.JPG'] if
                   os.path.splitext(name)[1] == item]

    image_names.sort(key=lambda x: int(x.split('.')[0]))  # 读取的图片顺序不规则,按顺序排序

    to_image = Image.new('RGB', (1 * 700, len(image_names) * 700))  # 创建一个空白新图, len(image_names) 计算文件中有多少张图片, 700 每张小图片的大小, 1 为 单列拼接
    # 循环遍历,把每张图片按顺序粘贴到空白图片对应位置上
    for y in range(1, len(image_names) + 1):
        for x in range(1, 1 + 1):
            from_image = Image.open(image_path + image_names[1 * (y - 1) + x - 1]).resize((700, 700), Image.ANTIALIAS)
            to_image.paste(from_image, ((x - 1) * 700, (y - 1) * 700))
    shutil.rmtree(image_path)   # 合并图片后,删除文件夹
    to_image.save(save_path)  # 保存图片

控制台:

代码语言:javascript
复制
if __name__ == '__main__':
    key = input('请输入你要下载的漫画:')
    data_path = r'D:/数据小刀/爬虫④/漫画/{}/'.format(key)
    if not os.path.exists(data_path):    # 根据用户输入的漫画名称创建文件夹
        os.mkdir(data_path)    
    url = f'https://www.kanman.com/api/getsortlist/?search_key={key}'   # 该url由去除不必要的参数得到
    get_comic(url)

文件夹保存效果展示:

拼接长图展示,图片太长,缩的小,看不清:

结语

  • 本文图片以及文本仅供学习、交流使用,不做商业用途,如有问题请及时联系我们以作处理。提供的结论仅供参考,还请独立思考。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python与Excel之交 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 爬取思路
  • 代码实现
  • 结语
相关产品与服务
云开发 CLI 工具
云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档