小言_互联网的博客

python爬虫找漫画出现断章?那你就得看这篇爬虫思想教学咯!

448人阅读  评论(0)

我们在爬取漫画的过程中,会不会觉得比爬一般的图片更困难一点? 今天我是遇到了, 但还是找了一些方法成功实现了它,那下面经验总结一下吧! 我是沙漏,关注我,不定期更新爬虫文章, 其他时间学linux 和 java 中!


【这很骚】好咧,废话不多说,这次我们爬的是一个国产动漫
============== 百妖谱 =================
网址: https://m.happymh.com/manga/baiyaopu
老规矩, 先讲爬虫思想, 后面再说代码实现。

爬虫思想:

漫画爬虫和其他图片的爬虫是不一样的, 如果是其他图片的爬取, 小可直接request抓取, 大可scrapy 框架全网抓, 这一次,我没有使用scrapy框架去爬这个网站, 理由如下:

  • 第一点, 我发现在csdn中讲scrapy框架而言, 访问量会很少, 一般都是爬虫新手小白居多, 这些人不是很懂这个框架的实现思想,对于知识点很难的讲, 其实效果还不如讲一点简易上手的小爬虫更加实在点,所以我还是用简单点的代码,效果更好哟。

  • 第二点, 刚开始看这个网站的时候, 我就发现有一点问题了, 存在一个这样的按钮, 如图:


  • 这是一个js按钮, 而且有开启的按钮, 还有收缩的按钮, 所以存在一个问题, 如果使用scrapy框架来说, 那么第一步就得在middle中去拦截这个请求,使用selenium去捕获, 天啊,这对于我们来说,太不友好了, 所以思考了一下,还是放弃了这个框架的使用, 于是转手简单的代码实现。

  • 其他思想:

  • 首先,我们需要使用 selenium 去自动的点击这个按钮, 这个必须掌握的,爬虫还是要会点其他技巧, 展示出全部章节之后,就可以获得章节的url链接了, 这个我想大家应该都会, 重要的一点, 就是漫画页面的解析,这个就很让我们纠结了, 解析三圣器soup re xpath 这三个到底选谁呢, 最后我还是选择了re , 为什么选择这个, 后面讲原因, 获得图片链接,之后就是下载环节了, 下载还是简单的, 只需要考虑到一点点因素,比如,章节标题,文件的重名混乱等等, 认真考虑下, 还是很容易做到的。


爬虫重要的点:

js按钮的问题:

【在上文中,我们讲到这个漫画爬虫有一个显示全部章节的按钮,所以我们要使用selenium去自动点击它,打开网页源代码, 我们查看一下 html网页, 如图:】

讲道理来说, 我们只需要定位到这个按钮, 然后点击它,就很顺利的完成了这个工作对吧, 但是经过我的代码测试, 结果还是出现了一个错误。
错误提示:Element:ElementClickInterceptedException
看了下, 发现是存在其他类是元素相互掩盖, 导致selenium无法正确的定位到这个按钮, 然后我回去看了下, 发现确实有一个 收起 按钮, 这二个按钮就相互冲突了, 开心的事情是,我成功的搞定了它,✌✌✌

get_all = self.browser.find_element_by_xpath('//*[@id="expandButton"]')
            #  有多个节点掩盖 该 按钮 使用如下js方式 可以避免
self.browser.execute_script("arguments[0].click();", get_all)

【这里至于为什么是0? 不用我说吧, 从0开始计数!】

技术感谢

页面url获取的点:


  • 大部分情况下, 我都是使用xpath去获取页面的节点来定位, 我觉得这样很快, xpath 确实很快, 但是在这个页面中, 我发现不能使用这个方式, 因为他所有url 都放在一个json数据包里面, 这样我们使用xpath就很难去处理所以我使用了正则, 直接去匹配这些页面, 效率一般, 但很简单理解。

正则匹配方式:

 title = re.search(r'.*?<title>(.*)</title>', r.text, re.S).groups(1)
 title = '-'.join(list(title)[0].split('-')[:2])
 img_urls = re.findall(r'{"width":"0","height":"0","url":"(.*?)","r":1,"next":0}', r.text, re.S

关于章节出现重名的点:

一般情况下,是不可能会出现章节同名的错误, 但结果我爬的这个文章,居然出现了这样的低级错误, 我的天啊, 这个前端人员是怎么写代码的, 好在,一山更比一山高,我可以搞你。

我是给了一个初始技术,也是用最笨的方式, 字符判定, 如果出现了这个章节, 那么就在后面 加 数字 123—这样的,如果我们不修改标题的名称, 那么就会出现文件夹重名, 文件夹重名是直接覆盖的方式的, 前面下载的文件就会丢失, 被重现掩盖掉, 所以这个点也需要注意,

self.count = 0
# 刚看到这只鸡有三个一样的章节, 在这里调试一下
if '媪姬篇' in title:
     title += str(self.count)
      self.count += 1

其他的点,我看起来就无关紧要了, 我的爬虫博客不会那么简单, 也不会那么复杂, 太简单的爬虫在我看来,没什么用处的, 只有文章有一定的难度,这样学习才有 动力, 才能获取知识,而不是按部就班, 墨守成规!

下面就是全部的代码, 看到这里, 觉得有用的朋友, 关注, 点赞, 支持一下, 多谢!!!

代码:

# -*- coding :  utf-8 -*-
# @Time      :  2020/7/21  21:18
# @author    :  沙漏在下雨
# @Software  :  PyCharm
# @CSDN      :  https://me.csdn.net/qq_45906219
import requests
from lxml import etree
from selenium import webdriver
import time
import os
import re


class Cartoon_BYP(object):
    """
    利用普通方式 搭配selenium去抓取该漫画
    后续 使用scrapy框架去搭配使用
    """

    def __init__(self):
        self.count = 1
        self.url = "https://m.happymh.com/manga/baiyaopu"
        self.params = {
   
            "Host": "m.happymh.com",
            "Referer": "https://cn.bing.com/",
            "Upgrade-Insecure-Requests": "1",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
                          " AppleWebKit/537.36 (KHTML, like Gecko) "
                          "Chrome/81.0.4044.129 Safari/537.36"
        }
        # 设置 selenium  浏览器
        self.browser = webdriver.Chrome()
        self.start()

    def start(self):
        """
        进行主页面的解析, 让浏览器自动点击 显示全部  这个按钮
        """
        try:
            self.browser.get(self.url)
            get_all = self.browser.find_element_by_xpath('//*[@id="expandButton"]')
            #  有多个节点掩盖 该 按钮 使用如下js方式 可以避免
            self.browser.execute_script("arguments[0].click();", get_all)
            time.sleep(0.5)
            print("按钮已经点击, 可以获得全部章节")
            html = self.browser.page_source
            for url in self.parse_home(html):
                title, img_urls = self.parse_chapter(url)
                self.down_img(title, img_urls)
            print('百妖谱全部下载完成!')

        except Exception as e:
            print('点击错误', e)

    def down_img(self, title, img_urls):
        """
        开始下载图片, 根据标题  和 网址
        """
        # 创建总目录
        path = r'D:/百妖谱/'
        if not os.path.exists(path):
            os.mkdir(path)
        # 创建章节目录
        os.chdir(path)
        # 刚看到这只鸡有三个一样的章节, 在这里调试一下
        if '媪姬篇' in title:
            title += str(self.count)
            self.count += 1
        if not os.path.exists(os.path.join(path, title)):
            os.mkdir(os.path.join(path, title))
            os.chdir(os.path.join(path, title))
        else:
            os.chdir(os.path.join(path, title))
        # 开始下载图片
        for _ in img_urls:
            time.sleep(1.2)
            r = requests.get(_, params=self.params)
            if r.status_code == 200:
                name = _.split('/')[-1]
                with open(name, 'wb') as fw:
                    fw.write(r.content)
                    print(f'{title}系列下载成功 {name}')
            else:
                # 如果404 则一直回溯
                self.down_img(title, _.split())
            print(r.status_code)

            # else:
            #     print('下载图片可能封Ip')

    def parse_home(self, html):
        """解析主页, 获得全部章节的网址,
        然后传给下载函数
        """
        html_ = etree.HTML(html)
        url = html_.xpath('//*[@id="limitList"]/div/div/a/@href')
        for i in url:
            yield i

    def parse_chapter(self, url):
        """
        解析首页
        """
        r = requests.get(url, params=self.params)
        if r.status_code == 200:
            title = re.search(r'.*?<title>(.*)</title>', r.text, re.S).groups(1)
            # title进行字符串处理 截取需要点
            title = '-'.join(list(title)[0].split('-')[:2])
            img_urls = re.findall(r'{"width":"0","height":"0","url":"(.*?)","r":1,"next":0}', r.text, re.S)
            return title, img_urls
        else:
            print('可能被封ip了, 需要稍等时间')


Cartoon_BYP()


转载:https://blog.csdn.net/qq_45906219/article/details/107520215
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场