scrapy的学习项目:每天都在进步,又是一个爬取图片的项目

我比较喜欢用写博客的方式来分析我的思路顺便分享我的代码

爬虫文件:pic360spider.py

# -*- coding: utf-8 -*-

import scrapy
import json
from urllib.parse import urlencode
from scrapy.http import Request
from pic360.items import Pic360Item



class Pic360spiderSpider(scrapy.Spider):
    name = 'pic360spider'
    allowed_domains = ['image.so.com']
    start_urls = ['https://image.so.com/zj?ch=beauty&sn=120&listtype=new&temp=1',
                  'https://image.so.com/zj?ch=beauty&sn=150&listtype=new&temp=1',
                  'https://image.so.com/zj?ch=beauty&sn=180&listtype=new&temp=1',
                  'https://image.so.com/zj?ch=beauty&sn=210&listtype=new&temp=1']

    def parse(self, response):
        json_res = json.loads(response.text)
        # 因为响应是一个json类型的实体,所已我用json解析一下
        if 'list' in json_res:
            for one_group in json_res.get('list'):

                pic_id = one_group.get('id')
                group_title = one_group.get('group_title')
                params = {'ch':'beauty','id':pic_id}
                paras = urlencode(params)
                # 当要为URL加入查询字符串的时候,这种方式很不错!
                group_url = 'https://image.so.com/zvj?'+paras

                yield Request(url=group_url,meta={'title':group_title},callback=self.par_group)
                # 对于meta原信息的传递,我感觉可以很熟练的应用了
                # meta理论上可以传递任意类型的数据给下一层函数

    def par_group(self,response):
        group_title = response.meta['title']
        json_resp = json.loads(response.text)
        image_urls = []
        if 'list' in json_resp:
            for pic_mes in json_resp.get('list'):
                pic_url = pic_mes.get('pic_url')
                # 这里注意在图片的url必须是一个列表,而从json中提取的是一个字符串,所以要用【】
                image_urls.append(pic_url)
            item = Pic360Item({'image_url':image_urls,'group_title':group_title})
            # 对于item的赋值,我们这里用字典的方式也是可以的
            # 这里我们减少了返回item的返回个数,通过将多个url添加到一个item的image_url中去,我们可以在一个item中返回多个url,注意:对于图片的下载我们的链接字段必须是列表
            yield item

管道文件:pipelines.py

from scrapy.pipelines.images import ImagesPipeline
from scrapy.http import Request
from scrapy.exceptions import DropItem

class Pic360Pipeline(object):

    def open_spider(self,spider):
        self.file = open('pic_mess.txt','w')
      # 爬虫开始运行时就会自动调用这个方法,打开文件

    def process_item(self, item, spider):
        self.file.write(item['group_title'])
        self.file.write('\n')
        return item
        # 用于处理item的函数(必须的),也是必须返回item

    def close_spider(self,spider):
        self.file.close()
        # 爬虫结束时自动调用,关闭文件
# 使用open_spider和close_spider避免了多次的IO操作
class MyImagePipeline(ImagesPipeline):
# 自定义的图片下载管道

    def get_media_requests(self, item, info):
        for image_url in item['image_url']:
        # 从这里我们可以看出来为什么image_url必须是一个列表了!
             yield Request(url=image_url)
             # 下载图片

    def item_completed(self, results, item, info):
    # 上面一个方法返回的results会自动传到这个方法中去
        image_path = [x['path'] for ok, x in results if ok]
        if not image_path:
            raise DropItem("此条目中没有图片")
        item['image_path'] = image_path
        return item
        # 也必须返回一个item

设置文件:settings.py

ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = 2

DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
    'Referer': 'https://image.so.com/zv?ch=beauty',
    'Host': 'image.so.com',
}

ITEM_PIPELINES = {
   'pic360.pipelines.Pic360Pipeline': 300,
    'pic360.pipelines.MyImagePipeline':1
}

IMAGES_STORE = 'D:/pictures/360pic'
# 这个是图片下载存储的位置
IMAGES_URLS_FIELD = 'image_url'
# 这个指明了图片下载管道应该在哪个字段获取图片下载的链接
IMAGES_RESULT_FIELD = 'image'
# 这个是图片结果的存储位置

# 这些设置是图片下载管道必须的(当然你可以选择默认的字段就不用)

items文件:items.py

from scrapy import Item,Field

class Pic360Item(Item):
    image_url = Field()
    image = Field()
    group_title = Field()
    image_path = Field()
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值