防盗链介绍:基础防盗链主要是针对客户端请求过程中所携带的一些关键信息来验证请求的合法性, 比如客户端请求IP,请求URL中携带的referer。优点是规则简单,配置和使用都很方便,缺点是防盗链所依赖的验证信息很多都是可以伪造的,因此此类防盗链可靠性较低。
创建工程:
scrapy startproject tutorial
2.创建蜘蛛
scrapy genspider imgSpider
3.创建爬取的Item
#图片下载管道
class ImageItem(scrapy.Item):
image_urls = scrapy.Field()
images = scrapy.Field()
image_name = scrapy.Field()
4.蜘蛛代码:网上很多用中间件的方式伪造referer,但是经过尝试是不可以的中间件在去访问资源的时候,拿到的referer和图片的链接一样这样的话图片会被重定向,具体看spider代码
import scrapy
from tutorial.items import ImageItem
class ImgspiderSpider(scrapy.Spider):
name = 'imgSpider'
allowed_domains = ['www.mm131.com']
start_urls = ['http://www.mm131.com/xinggan/',
'http://www.mm131.com/qingchun/',
'http://www.mm131.com/xiaohua/',
'http://www.mm131.com/chemo/',
'http://www.mm131.com/qipao/',
'http://www.mm131.com/mingxing/'
]
def parse(self, response):
list = response.css(".list-left dd:not(.page)")
for image in list:
image_name = image.css("a::text").extract_first()
image_url = image.css("a::attr(href)").extract_first()
image_url2 = str(image_url)
print(image_url2)
next_page = response.css(".page-en:nth-last-child(2)::attr(href)").extract_first()
if next_page is not None:
yield response.follow(next_page,callback=self.parse)
#下载图片
yield scrapy.Request(image_url2,callback=self.downloadImage)
def downloadImage(self,response):
item = ImageItem()
item['image_name'] = response.css(".content h5::text").extract_first()
item['image_urls'] = response.css(".content-pic img::attr(src)").extract()
print('---------------image_urls---------',item['image_urls'])
#防盗链:referer 从那个页面过来 没有来源就图片就会被重定向 解决办法在请求头中添加 headers={"referer":referer}
# 解决防盗链的最根本的就是告诉访问的资源的请求来自本站
item['referer'] = response.url
yield item
next_url = response.css(".page-ch:last-child::attr(href)").extract_first()
if next_url is not None:
yield response.follow(next_url,callback=self.downloadImage,dont_filter=True)
5.编写pipline处理下载的图片分组
class ImagePipline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item["image_urls"]:
print('-------------------image_url------------------------%s',image_url)
yield Request(image_url,meta={'name':item['image_name']},headers={'referer':item['referer']})
#重命名的功能 重写此功能可以得到自己想要文件名称 否则就是uuid的随机字符串
def file_path(self, request, response=None, info=None):
#图片名称
img_name = request.url.split('/')[-1]
#图片分类的名称
name = request.meta['name']
#处理特殊字符串
name = re.sub(r'[?\\*|“<>:/()0123456789]','',name)
#分文件夹存储
filename = u'{0}/{1}'.format(name,img_name)
return filename
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok,x in results if ok]
#上面的表达式等于
# for ok,x in results:
# if ok:
# print(x['path'])
if not image_paths:
raise DropItem('Item contains no images')
item['image_urls'] = image_paths
return item
.如果你看到下面的图片代表你成功了
屏幕快照 2019-01-02 19.46.05.png