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

  • A+
所属分类:Python

scrapy的学习项目:每天都在进步,又是一个爬取图片的项目 - 进入python的世界-killeri - CSDN博客

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()
-

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin