• Scrapy--Pyppeteer爬取加密网站01



    Pyppeteer的安装: pip install pyppeteer
    清华源安装: pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pyppeteer
    Pyppeteer可以直接饶过网站加密,从加载完的浏览器中直接抓取
    本次爬取的网站: Scrape Center spa6
    在这里插入图片描述

    1.网站检查:

    F12 检查页面 ——> 点击network,切换页面,发现加载出部分数据,点击第一条数据查看headers
    Request URL:
    https://spa6.scrape.center/api/movie?limit=10&offset=10&token=MjEzMmE3MTIxOTdjNzEzNWQyMzc5OWVmN2U1MjYxNGYxZmRkNWM0ZSwxNjU1ODYwOTEw
    在这里插入图片描述
    这一串为加密字符:token=MjEzMmE3MTIxOTdjNzEzNWQyMzc5OWVmN2U1MjYxNGYxZmRkNWM0ZSwxNjU1ODYwOTEw

    由此可知,网站数据是由api调用,并进行了加密,若没学习过Javascript逆向,则可以使用Pyppeteer调用;

    2.项目实施:

    2.1 Scrapy项目创建:

    创建Scrapy项目:

    1. 在终端中找到需要创建项目的目录;
    2. scrapy startproject spa6 spa6为项目名,scrapy startproject为固定语法;
    3. 进入到spa6文件夹中,cd spa6
    4. scrapy genspider example example.com 后面两随便写即可

    2.2 项目准备:

    在Scrapy项目创建过程中,我写的第一个example是app1,所以在文件夹spider中就可以看见一个app1.py文件,点开它
    在这里插入图片描述
    这就是项目的主文件,需要进行爬取的操作均在这里实现;
    app1.py导入Pyppeteer库,from gerapy_pyppeteer import PyppeteerRequest

    import scrapy
    from gerapy_pyppeteer import PyppeteerRequest
    
    class App1Spider(scrapy.Spider):
        name = 'app1'
        # allowed_domains = ['df']
        # start_urls = ['http://df/']
    
        def start_requests(self):
            url = "https://spa6.scrape.center/page/2"
            # 使用Pyppeteer 等待class = m-b-sm元素出现
            yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')
    
        def show(self, response):
            print(response.text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    关键代码:

    yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')
    
    • 1

    参数一:用于传递url;
    参数二:指定传递数据的函数;这里指定的是show函数;
    参数三:等待一个元素加载出来,这里等待的是class类 .m-b-sm

    此时还需要做另一些准备,将Pyppeteer与Scrapy对接
    项目关键:
    setting.py文件夹中
    更改 DOWNLOADER_MIDDLEWARES
    实现Pyppeteer的对接middlewares,使用Pyppeteer中的下载器

    DOWNLOADER_MIDDLEWARES = {
        # 'spa6.middlewares.Spa6DownloaderMiddleware': 543,
        'gerapy_pyppeteer.downloadermiddlewares.PyppeteerMiddleware': 543,
    }
    # 指定不加载的数据类型,image图片,font字体文件
    GERAPY_PYPPETEER_IGNORE_RESOURCE_TYPES = ['image', 'font']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    末尾加入

    # 对接pyppeteer
    CONCURRENT_REQUESTS = 3
    GERAPY_PYPPETEER_HEADLESS = False
    # 反屏蔽
    GERAPY_PYPPETEER_PRETEND = True
    # 设置超时时间
    GERAPY_PYPPETEER_DOWNLOAD_TIMEOUT = 30
    # 设置窗口大小
    GERAPY_PYPPETEER_WIDTH = 1400
    GERAPY_PYPPETEER_HEIGHT = 700
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Scrapy的运行
    需要在终端中输入 scrapy crawl 项目名,项目名就是app1.py文件中的name参数,我这里就是app1;
    接下来介绍,一种更加方便的方法,就不用每次都在终端中输入直接运行就可以了
    创建一个启动文件,run.py
    在这里插入图片描述
    run.py文件代码,要启动Scrapy项目直接运行run.py即可

    from scrapy.cmdline import execute
    execute(['scrapy', 'crawl', 'app1'])
    
    • 1
    • 2

    2.3 项目流程:

    一下代码是在app1.py主文件中的show()函数内
    导入lxml库中的etree,from lxml import etree
    该代码检查是否可以获得数据,由于是异步执行,所以获取数据的顺序不一定一致;

    def show(self, response):
        source = response.text
    	demo = etree.HTML(source).xpath('//h2[@class="m-b-	sm"]/text()')
    	print(demo)
    
    • 1
    • 2
    • 3
    • 4

    即可测试能否爬取到数据

    项目翻页有两种方法实现,方法一是直接通过更改网页链接进行翻页;
    方法二是通过Pyppeteer的鼠标控制进行翻页;

    方法一:使用for循环翻页

    import scrapy
    from gerapy_pyppeteer import PyppeteerRequest
    from lxml import etree
    
    class App1Spider(scrapy.Spider):
        name = 'app1'
        # allowed_domains = ['df']
        # start_urls = ['http://df/']
    
        def start_requests(self):
            # 翻页
            for i in range(1, 4):
                url = "https://spa6.scrape.center/page/{}".format(i)
                yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')
            # 使用Pyppeteer 等待class = m-b-sm元素出现
    
    
        def show(self, response):
            source = response.text
            # 获取页面中10个div[@class="el-card__body"]
            demo = etree.HTML(source).xpath('//div[@class="el-card__body"]')
            for i in demo:
                # 获取标题
                title = i.xpath('div[1]/div[2]/a/h2/text()')[0]
                category = i.xpath('div[1]/div[2]/div[1]//text()')
                # category是一个列表,所以使用map函数解析列表,并执行操作;str.strip消除空格;再用|拼接
                category = '|'.join(map(str.strip, category))
                print(title)
                print(category)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    方法二:使用点击控制翻页
    需要载入一个异步包 asyncio
    在类外创建一个异步函数

    import asyncio
    
    async def hello(page):
        await page.click('.btn-next')
    
    • 1
    • 2
    • 3
    • 4
        def start_requests(self):
            # 翻页
            url = "https://spa6.scrape.center/page/1"
            yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm', actions=hello)
    
    • 1
    • 2
    • 3
    • 4

    翻页:yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm', actions=hello)
    actions = hello为调用hello函数

    翻页的思路是:设定一个类参数page,用于记录翻页情况,没翻一次减去一次page,便于指定爬取页数

    import scrapy
    from gerapy_pyppeteer import PyppeteerRequest
    from lxml import etree
    import asyncio
    
    async def hello(page):
        await page.click('.btn-next')
    
    class App1Spider(scrapy.Spider):
        name = 'app1'
        # allowed_domains = ['df']
        # start_urls = ['http://df/']
        page = 10
    
        def start_requests(self):
            # 翻页
            url = "https://spa6.scrape.center/page/1"
            yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')
    
        def show(self, response):
            print(response.url)
            source = response.text
            # 获取页面中10个div[@class="el-card__body"]
            demo = etree.HTML(source).xpath('//div[@class="el-card__body"]')
            for i in demo:
                # 获取标题
                title = i.xpath('div[1]/div[2]/a/h2/text()')[0]
                category = i.xpath('div[1]/div[2]/div[1]//text()')
                # category是一个列表,所以使用map函数解析列表,并执行操作;str.strip消除空格;再用|拼接
                category = '|'.join(map(str.strip, category))
                print(title, category)
            App1Spider.page = App1Spider.page - 1
            if App1Spider.page > 0:
                yield PyppeteerRequest(response.url, callback=self.show, wait_for='.m-b-sm', actions=hello, dont_filter=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    yield PyppeteerRequest(response.url, callback=self.show, wait_for=‘.m-b-sm’, actions=hello, dont_filter=True),
    该处加入了 dont_filter参数
    Scrapy中是默认开启过滤,默认dont_filter = False
    我们第一次传入url时已经使用过了response.url,当我们进行函数回调时,系统会把重复的url删除,这样就不能进行回调了,所以要把回调机制关闭

  • 相关阅读:
    【无标题】
    【python第三方库】easydict的使用
    DTC趋势 | 2022年值得关注的10个DTC趋势
    智慧矿山解决方案-最新全套文件
    Linux:在线扩容
    猿创征文|Python迭代器、生成器、装饰器、函数闭包
    Lesson4-1:OpenCV图像特征提取与描述---角点特征
    array_map与array_walk的用法与区别详解
    对象数组转成strin再进行,隔开的字符串,包括赛选某个字段的子,或者求和,
    基金客户和销售机构
  • 原文地址:https://blog.csdn.net/weixin_44826986/article/details/125402890