斗鱼App妹子图下载

创建项目'douyu'

  1. scrapy startproject douyu

树形图展示项目

  1. cd douyu/
  2. tree

图片下载之斗鱼App妹子 - 图1

Sublime打开项目

  1. subl .

图片下载之斗鱼App妹子 - 图2

生成采集模块spider

  • genspider 在当前项目中创建spider。

    语法: scrapy genspider [-t template] <name> <domain>

  1. $ scrapy genspider -l
  2. Available templates:
  3. basic
  4. crawl
  5. csvfeed
  6. xmlfeed
  7. $ scrapy genspider -d basic
  8. import scrapy
  9. class $classname(scrapy.Spider):
  10. name = "$name"
  11. allowed_domains = ["$domain"]
  12. start_urls = (
  13. 'http://www.$domain/',
  14. )
  15. def parse(self, response):
  16. pass
  17. $ scrapy genspider -t basic example example.com
  18. Created spider 'example' using template 'basic' in module:
  19. mybot.spiders.example

创建:

  1. scrapy genspider douyu_spider douyucdn.cn

图片下载之斗鱼App妹子 - 图3

编辑项目

item.py

  1. import scrapy
  2. class DouyuItem(scrapy.Item):
  3. # define the fields for your item here like:
  4. data = scrapy.Field()
  5. image_path = scrapy.Field()
  6. pass

setting.py

设置 USER_AGENT

  1. USER_AGENT = 'DYZB/2.271 (iPhone; iOS 9.3.2; Scale/3.00)'

douyu_spider.py

  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3. '''添加内容'''
  4. from douyu.items import DouyuItem
  5. import json
  6. class DouyuSpiderSpider(scrapy.Spider):
  7. name = 'douyu_spider'
  8. allowed_domains = ["douyucdn.cn"]
  9. '''添加内容'''
  10. offset = 0
  11. start_urls = (
  12. 'http://capi.douyucdn.cn/api/v1/getVerticalRoom?limit=20&offset='+str(offset),
  13. )
  14. def parse(self, response):
  15. '''添加内容'''
  16. data=json.loads(response.body)['data']
  17. if not data:
  18. return
  19. for it in data:
  20. item = DouyuItem()
  21. item['image_url']=it['vertical_src']
  22. item['data']=it
  23. yield item
  24. self.offset+=20
  25. yield scrapy.Request('http://capi.douyucdn.cn/api/v1/getVerticalRoom?limit=20&offset=%s'%str(self.offset),callback=self.parse)

pipeline.py

文件系统存储: 文件以它们URL的 SHA1 hash 作为文件名

sha1sumsha1sum对文件进行唯一较验的hash算法,用法: sha1sum [OPTION] [FILE]…参数: -b, —binary 二进制模式读取 -c, —check 根据sha1 num检查文件 -t, —text 文本模式读取(默认)

举例:

  1. f51be4189cce876f3b1bbc1afb38cbd2af62d46b scrapy.cfg

{ 'image_path': 'full/9fdfb243d22ad5e85b51e295fa60e97e6f2159b2.jpg', 'image_url': u'http://staticlive.douyucdn.cn/upload/appCovers/845876/20160816/c4eea823766e2e5e018eee6563e4c420_big.jpg'}

测试:

  1. sudo vi test.txt
  2. 拷贝内容
  3. http://staticlive.douyucdn.cn/upload/appCovers/845876/20160816/c4eea823766e2e5e018eee6563e4c420_big.jpg
  4. sha1sum test.txt
  5. 9fdfb243d22ad5e85b51e295fa60e97e6f2159b2 test.txt

参考文档:

http://doc.scrapy.org/en/latest/topics/media-pipeline.html

注意:项目环境 Scrapy 1.0.3 class scrapy.pipelines.images.ImagesPipeline项目环境 Scrapy 1.0 class scrapy.pipeline.images.ImagesPipeline

下面是你可以在定制的图片管道里重写的方法:

class scrapy.pipelines.images.ImagesPipeline

  • get_media_requests(item, info)

    管道会得到文件的URL并从项目中下载。需要重写 get_media_requests() 方法,并对各个图片URL返回一个Request:

  1. def get_media_requests(self, item, info):
  2. for image_url in item['image_urls']:
  3. yield scrapy.Request(image_url)

当它们完成下载后,结果将以2-元素的元组列表形式传送到item_completed() 方法 results 参数: 每个元组包含 (success, file_info_or_error):

  • success 是一个布尔值,当图片成功下载时为 True,因为某个原因下载失败为False

  • file_info_or_error 是一个包含下列关键字的字典(如果成功为 True)或者出问题时为TwistedFailure

    • url - 文件下载的url。这是从 get_media_requests() 方法返回请求的url。
    • path - 图片存储的路径
    • checksum - 图片内容的 MD5 hash下面是 item_completed(results, items, info)中 results 参数的一个典型值:
  1. [(True,
  2. {'checksum': '2b00042f7481c7b056c4b410d28f33cf',
  3. 'path': 'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg',
  4. 'url': 'http://staticlive.douyucdn.cn/upload/appCovers/420134/20160807/f18f869128d038407742a7c533070daf_big.jpg'}),
  5. (False,
  6. Failure(...))]

默认 get_media_requests() 方法返回 None ,这意味着项目中没有文件可下载。

  • item_completed(results, items, info)

    当图片请求完成时(要么完成下载,要么因为某种原因下载失败),该方法将被调用

    item_completed() 方法需要返回一个输出,其将被送到随后的项目管道阶段,因此你需要返回(或者丢弃)项目

    举例:

    其中我们将下载的图片路径(传入到results中)存储到file_paths 项目组中,如果其中没有图片,我们将丢弃项目:

  1. from scrapy.exceptions import DropItem
  2. def item_completed(self, results, item, info):
  3. image_paths = [x['path'] for ok, x in results if ok]
  4. '''
  5. image_paths=s[]
  6. for ok, x in results:
  7. if ok:
  8. image_paths.append(x['path'])
  9. return image_paths
  10. '''
  11. if not image_paths :
  12. raise DropItem("Item contains no images")
  13. item['image_paths'] = image_paths
  14. return item

默认情况下,item_completed()方法返回项目

定制图片管道:

下面是项目图片管道

  1. import scrapy
  2. from scrapy.pipelines.images import ImagesPipeline
  3. from scrapy.exceptions import DropItem
  4. class ImagesPipeline(ImagesPipeline):
  5. def get_media_requests(self, item, info):
  6. image_url = item['image_url']
  7. yield scrapy.Request(image_url)
  8. def item_completed(self, results, item, info):
  9. image_paths = [x['path'] for ok, x in results if ok]
  10. if not image_paths:
  11. raise DropItem("Item contains no images")
  12. item['image_path'] = image_paths[0]
  13. return item

启用pipelines

设置图片下载位置

是定义在 IMAGES_STORE 设置里的文件夹
  1. IMAGES_STORE = '/home/python/project/douyu/photos'

启用PIPELINES:设置item后处理模块

  1. ITEM_PIPELINES = {
  2. 'douyu.pipelines.ImagesPipeline': 300,
  3. }

运行爬虫

  1. scrapy runspider douyu/spiders/douyu_spider.py
  2. 或者是 scrapy crawl douyu_spider

项目还缺什么

item存储

pipeline.py编写

  1. import json
  2. import codecs
  3. class JsonWriterPipeline(object):
  4. def __init__(self):
  5. self.file = codecs.open('items.json', 'w', encoding='utf-8')
  6. def process_item(self, item, spider):
  7. line = json.dumps(dict(item), ensure_ascii=False) + "\n"
  8. self.file.write(line)
  9. return item
  10. def spider_closed(self, spider):
  11. self.file.close()

启用JsonWriterPipeline编写

  1. ITEM_PIPELINES = {
  2. 'douyu.pipelines.ImagesPipeline': 300,
  3. 'douyu.pipelines.JsonWriterPipeline': 800,
  4. }

再次运行

  1. scrapy crawl douyu_spider