美文网首页测试开发程序员我的Python自学之路
Python爬虫实战-使用Scrapy框架爬取土巴兔(五)

Python爬虫实战-使用Scrapy框架爬取土巴兔(五)

作者: imflyn | 来源:发表于2017-03-18 19:13 被阅读1287次

    上一篇文章Python爬虫实战-使用Scrapy框架爬取土巴兔(四)我们为爬虫工程定制了具体的爬取规则,那么接下来就要进一步处理爬取到的信息,并将它们持久化。

    该系列其它文章


    该篇文章主要讲在Scrapy中运用Item Pipeline对Spider中收集到的Item进行具体的处理。

    一.下载图片

    在Spider收集到的Item对象中,我们可以拿到图片的URL。我们要做的就是对图片进行下载、保存。

    class DesignPicturePipeline(object):
        def __init__(self):
            self.design_picture_service = DesignPictureService()
    
        def process_item(self, item, spider):
            img_url = item['img_url']
            #获取文件名
            img_name = ImageService.generate_name(img_url)
            #获取文件路径
            file_path = ImageService.file_path(img_name)
            #获取缩略图路径
            thumb_path = ImageService.thumb_path(img_name)
            #下载图片并保存
            ImageService.download_img(img_url, file_path)
            #保存缩略图
            ImageService.save_thumbnail(file_path, thumb_path)
            item['img_name'] = img_name
            #保存到MongoDB
            self.design_picture_service.handle_item(item)
    

    下载图片时我们用到http请求库requests

    def download_img(img_url, file_path):
        proxies = None
        proxy = ''
        if config.USE_PROXY:
            proxy = proxy_pool.random_choice_proxy()
            proxies = {
                'http': "http://%s" % proxy,
            }
        try:
            response = requests.get(img_url, stream=True, proxies=proxies)
            if response.status_code == 200:
                with open(file_path, 'wb') as f:
                    for chunk in response.iter_content(1024):
                        f.write(chunk)
            else:
                if config.USE_PROXY:
                    proxy_pool.add_failed_time(proxy)
        except:
            if config.USE_PROXY:
                proxy_pool.add_failed_time(proxy)
    

    保存缩略图时使用了处理图片的开源库pillow,先对图片进行裁剪,然后保存到指定路径

    from PIL import Image
    
    IMAGE_SIZE = 500, 500
    def save_thumbnail(file_path, thumb_path):
        image = Image.open(file_path)
        if thumb_path is not None:
            image.thumbnail(IMAGE_SIZE)
            image.save(thumb_path)
        del image
    

    Scrapy也提供了ImagesPipeline来对图片进行下载及裁剪。但如果我们需要高度定制还是需要自己完成下载图片的逻辑代码。

    二.保存数据

    TABLE_NAME = "design_picture"
    
    def handle_item(self, design_picture_item: DesignPictureItem):
        #设置埋点,判断是否为重复的URL
        if self.is_duplicate_url(design_picture_item['img_url']):
            return
        #创建保存到数据库中的实体对象
        design_picture_model = self.get_design_picture_model(design_picture_item)
        #保存到MongoDB
        try:
            collection = Collection(mongodb, TABLE_NAME)
            collection.insert_one(item.__dict__)
        except Exception as e:
            log.error(e)
    

    保存在MongoDB中的数据格式:

    {
        "_id" : ObjectId("58cbd1f8ca6e1d0be0b1f329"),
        "img_height" : "458",
        "img_url" : "http://pic.to8to.com/case/1702/13/20170213_57a89af924138e15ab34ftkozxmlx8li.jpg",
        "description" : "北欧风慵懒休闲感一居室图片",
        "html_url" : "http://xiaoguotu.to8to.com/getxgtjson.php?a2=0&a12=&a11=10043653&a1=0",
        "id" : "91de71b0-0b0a-11e7-9909-94de802721e7",
        "create_time" : "2017-03-17T12:09:28.294Z",
        "img_name" : "/tubatu/2017-03-17/41ec3e630289177dda3a91ad89a1ba72",
        "sub_title" : "北欧风慵懒休闲感一居室图片",
        "title" : "北欧风慵懒休闲感一居室图片",
        "tags" : [ 
            "北欧", 
            "一居"
        ],
        "img_width" : "780",
        "fid" : "8a42487a-0b0a-11e7-9f80-94de802721e7"
    }
    

    三.启动Scrapy

    Scrapy提供了Shell命令来启动爬虫但是如果需求不同,需要自定义逻辑还是在python文件中启动。
    为了保证爬虫的长时间工作,需要开启定时任务检查爬虫是否在运行状态,如果爬取已经结束了则重新开始。

    import os
    import sys
    import threading
    import time
    from os.path import dirname
    
    from schedule import Scheduler
    from twisted.internet import reactor
    
    from tubatu import config
    
    #需要引用外层文件夹中文件,将工程中的所有文件夹加入环境变量中
    path = dirname(os.path.abspath(os.path.dirname(__file__)))
    sys.path.append(path)
    
    
    class Runner(object):
        def __init__(self):
            self.is_running = False
            #将引擎关闭的回调与自定义关闭爬虫方法绑定
            dispatcher.connect(self.pause_crawler, signals.engine_stopped)
            #获取settings.py中配置
            self.setting = get_project_settings()
            self.process = None
    
        def start_scrapy(self):
            #创建爬虫进程
            self.process = CrawlerProcess(self.setting)
            self.crawl()
            reactor.run()
    
        def pause_crawler(self):
            self.is_running = False
            print("============ 爬虫已停止 ===================")
        
        #启动爬虫
        def crawl(self):
            self.is_running = True
            self.process.crawl(DesignPictureSpider())
            
        
        #启动IP代理池
        def start_proxy_pool(self):
            from msic.proxy.proxy_pool import proxy_pool
            if config.USE_PROXY:
                proxy_pool.start()
            else:
                proxy_pool.drop_proxy()
    
        def run(self):
            self.start_proxy_pool()
            self.start_scrapy()
    
    
    if __name__ == '__main__':
        runner = Runner()
    
    
        def thread_task():
            def task():
                if not runner.is_running:
                    print("============ 开始重新爬取 ===================")
                    runner.crawl()
            
            #创建定时任务,没过30分钟检查爬虫是否关闭了,如果关闭了重新启动
            schedule = Scheduler()
            schedule.every(30).minutes.do(task)
    
            while True:
                schedule.run_pending()
                time.sleep(1)
    
    
        thread = threading.Thread(target=thread_task)
        thread.start()
    
        runner.run()
    

    最后

    至此,Python爬虫实战-使用Scrapy框架爬取土巴兔教程已经全部结束。感谢读者的阅读,文章希望能帮到大家。

    附:

    详细的项目工程在Github中,如果觉得还不错的话记得Star哦。

    相关文章

      网友评论

      • 觉释:初次发表意见,写的清晰明了,对学习爬虫的非常有帮助。
      • imXuJ:思路清晰,没有废话,文笔流畅,怎能不膜拜
      • seven1010:写的太好了
      • 慢慢慢慢热:好厉害,别的不说,光是学会了这个项目的思路就感觉很棒了,且不说代码实现。
      • LLS不想挂机了:目前看过最详尽的教程了~赞👍

      本文标题:Python爬虫实战-使用Scrapy框架爬取土巴兔(五)

      本文链接:https://www.haomeiwen.com/subject/euhpnttx.html