minimize相关知识
-
提升网站性能最佳实践提升网站性能最佳实践---Best Practices for Speeding Up Your Web Site The Exceptional Performance team has identified a number of best practices for making web pages fast. The list includes 35 best practices divided into 7 categories. 01.Minimize HTTP Requests---减少http请求 simplify the page's design. 2.Combined files 3.Image maps 4.CSS Sprites 5.Inline images---are not yet supported across all major br
-
LeetCode 283:移动零 Move Zeroes给定一个数组 `nums`,编写一个函数将所有 `0` 移动到数组的末尾,同时保持非零元素的相对顺序。Given an array `nums`, write a function to move all `0`'s to the end of it while maintaining the relative order of the non-zero elements.**示例:**```输入: [0,1,0,3,12]输出: [1,3,12,0,0]```**说明**:1. 必须在原数组上操作,不能拷贝额外的数组。2. 尽量减少操作次数。**Note**:1. You must do this **in-place** without making a copy of the array.2. Minimize the total number of operations.### 解题思路: 千万不要被题目局限了思维!题目让把所有0移到末尾,如果你的思路是遇零与末尾数字交换位置,然后还需要把非
-
你真的知道计算机是如何进行减法运算的吗?问:现在的时间是3点钟,如何转动时针,让时间到达2点钟呢? 答:减去1小时,亦或是加上11小时。 问:图中一个字节的无符号数值,它代表十进制数据 2, 如何让它变成1呢? 答:减去1,亦或是加上255。 因为时钟旋转一周为360°,所以顺时针旋转330°,也就等于逆时针旋转30°(360° - 330°); 因为一个字节的无符号数值最多表现为256种数值状态,所以减1,也就等于加255(256 - 1)。 也就是说: 2 - 1 = 2 + (256 - 1) = 2 + 255 = 257 = 257 - 256(减去溢出
-
Android 玩转PathMeasure之自定义支付结果动画概述最近在研究Android的路径动画,恕我直言,PathMeasure是个神器,可以帮助我们绘制任意的路径,只要你能draw出来的Path,它都能绘制出来,你可能会问,既然drawPath都可以了,要它何用? PathMeasure的强大之处在于它能够通过根据起点和终点截取某一段路径进行绘制,可以理解为对Path片段的绘制,然你可能还是会说:但如果再结合属性动画,那简直就可以为所欲为了。突然想到之前遇到过的一些支付场景经常会有一个支付状态的展示动画,就是一直循环转圈然后最终打勾或者打叉的效果,感觉也可以用路径动画写一个,最终效果图如下:加载动画效果图 需要定制的特性1.绘制的颜色2.线条的粗细3.加载状态下每圈的速度4.打勾或打叉的速度 实现思路可以看到这个View主要由两部分组成,1.旋转加载中的动画。 2.展示结果的动画。可以分为各自的路径和动画器进行实现,一开始循环加载动画,直到传进结果才切换为结果动画,转圈动画可以用一条Circle路径结合ValueAnimator进行绘制,结
minimize相关课程
minimize相关教程
- 2.2 Scrapy 框架内置的 Pipelines 分析 前面第12节中,我们在介绍 Scrapy 框架的管道内容时,使用了其内置的图片处理管道 (ImagesPipeline),它对应的代码位置为:scrapy/pipelines/images.py。接下来,我们将分析其源码,看看如何实现图片下载的功能。首先看看类继承关系:在 images.py 中定义的 ImagesPipeline 继承了 files.py 中定义的 FilesPipeline 类;而 FilesPipeline 类又继承至 media.py 中定义的 MediaPipeline 类。因此,我们先从分析基类开始,我们从管道的两个核心方法开始入手:初始化方法:__init__() ;Item 核心处理方法:process_item();首先来看初始化的代码,如下:# 源码位置:scrapy/pipelines/media.py# ...class MediaPipeline: LOG_FAILED_RESULTS = True class SpiderInfo: def __init__(self, spider): self.spider = spider self.downloading = set() self.downloaded = {} self.waiting = defaultdict(list) def __init__(self, download_func=None, settings=None): self.download_func = download_func if isinstance(settings, dict) or settings is None: settings = Settings(settings) resolve = functools.partial(self._key_for_pipe, base_class_name="MediaPipeline", settings=settings) self.allow_redirects = settings.getbool( resolve('MEDIA_ALLOW_REDIRECTS'), False ) self._handle_statuses(self.allow_redirects) def _handle_statuses(self, allow_redirects): # 默认不允许重定向 self.handle_httpstatus_list = None if allow_redirects: # 当设置了allow_redirects时,会考虑处理存在3xx的下载地址 self.handle_httpstatus_list = SequenceExclude(range(300, 400)) def _key_for_pipe(self, key, base_class_name=None, settings=None): """ >>> MediaPipeline()._key_for_pipe("IMAGES") 'IMAGES' >>> class MyPipe(MediaPipeline): ... pass >>> MyPipe()._key_for_pipe("IMAGES", base_class_name="MediaPipeline") 'MYPIPE_IMAGES' """ class_name = self.__class__.__name__ formatted_key = "{}_{}".format(class_name.upper(), key) if ( not base_class_name or class_name == base_class_name or settings and not settings.get(formatted_key) ): return key return formatted_key # ...上面的类中又定义了一个类:SpiderInfo ,这个类只是用来保存多个数据用的。此外,初始化方法中主要读取相关的配置,判断是否需要允许下载的 URL 重定向。该参数在 Scrapy 官方文档中的说明如下:处理管道媒体文件下载地址重定向问题接下来是核心的处理 Item 的方法:# 源码位置:scrapy/pipelines/media.py# ...class MediaPipeline: # ... def process_item(self, item, spider): info = self.spiderinfo # 从item中获取请求列表 requests = arg_to_iter(self.get_media_requests(item, info)) # 形成相关的处理链表 dlist = [self._process_request(r, info) for r in requests] dfd = DeferredList(dlist, consumeErrors=1) # 上述的处理全部完成后的回调 return dfd.addCallback(self.item_completed, item, info) # ...我们知道管道类中处理 Item 的核心方法是 process_item() ,上面的 process_item() 方法先调用对象的 get_media_requests() 方法从输入的 item 中获取相应的请求列表,然后在形成对应的请求列表,处理请求的方法为:_process_request(),最后所有的请求完成后会执行对象的 item_completed() 方法。# 源码位置:scrapy/pipelines/media.py# ...class MediaPipeline: # ... def get_media_requests(self, item, info): """Returns the media requests to download""" pass # ...这个 get_media_requests() 需要在后续的继承类中实现。接下来看处理下载请求的方法:# 源码位置:scrapy/pipelines/media.py# ...class MediaPipeline: # ... def _process_request(self, request, info): # 每个请求计算一个指纹,以保证后面不重复请求 fp = request_fingerprint(request) # 请求回调 cb = request.callback or (lambda _: _) # 请求错误回调 eb = request.errback request.callback = None request.errback = None # 如果已经请求过了,直接取缓存的结果 if fp in info.downloaded: return defer_result(info.downloaded[fp]).addCallbacks(cb, eb) # Otherwise, wait for result wad = Deferred().addCallbacks(cb, eb) # 将请求的回调链加入对应的请求key中 info.waiting[fp].append(wad) # 检查请求是否正在下载中,避免二次请求 if fp in info.downloading: return wad # 将请求加入正在下载的队列 info.downloading.add(fp) # 创建Deferred对象,对应方法为self.media_to_download() dfd = mustbe_deferred(self.media_to_download, request, info) # 在self.media_to_download()方法处理完后回调self._check_media_to_download()方法 dfd.addCallback(self._check_media_to_download, request, info) # 此外,再加入统一回调方法 dfd.addBoth(self._cache_result_and_execute_waiters, fp, info) dfd.addErrback(lambda f: logger.error( f.value, exc_info=failure_to_exc_info(f), extra={'spider': info.spider}) ) return dfd.addBoth(lambda _: wad) # it must return wad at last # ...上面请求的过程在注释中已详细说明,这里处理下载请求主要涉及的方法为:self.media_to_download() 以及 self._check_media_to_download()。我们继续查看该方法的代码:# 源码位置:scrapy/pipelines/media.py# ...class MediaPipeline: # ... # Overridable Interface def media_to_download(self, request, info): """Check request before starting download""" pass def _check_media_to_download(self, result, request, info): if result is not None: return result if self.download_func: # this ugly code was left only to support tests. TODO: remove dfd = mustbe_deferred(self.download_func, request, info.spider) dfd.addCallbacks( callback=self.media_downloaded, callbackArgs=(request, info), errback=self.media_failed, errbackArgs=(request, info)) else: self._modify_media_request(request) # 将请求发给引擎模块,调用download()方法下载网页 dfd = self.crawler.engine.download(request, info.spider) dfd.addCallbacks( callback=self.media_downloaded, callbackArgs=(request, info), errback=self.media_failed, errbackArgs=(request, info)) return dfd # ...可以看到 media_to_download() 方法也是在继承类中需要重写的,而 _check_media_to_download() 方法则是核心处理下载文件或者图片的地方。该方法中首先判断是否有传入的 download_func() 方法用于下载网页,如果没有则调用引擎模块中的 download() 方法下载网页数据,成功后调用 media_downloaded() 方法,失败则调用 media_failed() 方法。最后我们来看下 self._cache_result_and_execute_waiters() 方法,其内容和逻辑比较简单,就是缓存请求的数据并将请求清除等待队列:# 源码位置:scrapy/pipelines/media.py# ...class MediaPipeline: # ... def _cache_result_and_execute_waiters(self, result, fp, info): if isinstance(result, Failure): # minimize cached information for failure result.cleanFailure() result.frames = [] result.stack = None context = getattr(result.value, '__context__', None) if isinstance(context, StopIteration): setattr(result.value, '__context__', None) # 下载队列中移除该请求 info.downloading.remove(fp) # 缓存下载请求结果 info.downloaded[fp] = result # 移除等待队列中的该请求 for wad in info.waiting.pop(fp): # 将原来请求的回调方法以及错误回调方法,加入回调处理链 defer_result(result).chainDeferred(wad)此时,我们总结下 MediaPipeline 类的核心处理流程:管道下载媒体数据详细流程到此,MediaPipeline 类的核心方法我们已经研究完毕,接下来开始继续学习 MediaPipeline 这个类。注意到该类中并没有 process_item() 方法,因此它直接继承父类的 process_item() 方法。从 MediaPipeline 类中可知在 _check_media_to_download() 方法中会下载相应的媒体文件,成功后会回调 media_downloaded() 方法# 源码位置:scrapy/pipelines/files.py# ...class FilesPipeline(MediaPipeline): # ... def media_downloaded(self, response, request, info): referer = referer_str(request) if response.status != 200: # 打印告警信息,下载失败 # ... raise FileException('download-error') if not response.body: # 打印告警信息,无下载内容 # ... raise FileException('empty-content') status = 'cached' if 'cached' in response.flags else 'downloaded' # 打印debug信息 self.inc_stats(info.spider, status) try: # 设置下载文件路径 path = self.file_path(request, response=response, info=info) # 将下载的内容保存成本地文件 checksum = self.file_downloaded(response, request, info) except FileException as exc: # 打印异常信息 # ... raise except Exception as exc: # 打印异常信息 # ... raise FileException(str(exc)) return {'url': request.url, 'path': path, 'checksum': checksum, 'status': status} # ...从上面的代码可知,在请求成功后,下载的内容保存在 response.body 中,上面的代码就是将该文件内容保存成磁盘上的文件:# 源码位置:scrapy/pipelines/files.py# ...class FilesPipeline(MediaPipeline): # ... def file_downloaded(self, response, request, info): # 生成文件保存路径 path = self.file_path(request, response=response, info=info) # 获取字节流形式的下载内容 buf = BytesIO(response.body) checksum = md5sum(buf) buf.seek(0) # 持久化保存 self.store.persist_file(path, buf, info) # 返回文件的md5值 return checksum上面的代码是不是已经够清楚了?最后文件内容是 buf,保存的方法是 self.store.persist_file(path, buf, info),该方法是支持将下载内容保存成多种形式,比如保存到本地文件中、保存到 FTP 服务器上,甚至可以通过 S3 接口保存到云存储中。来看看保存成本地文件形式的代码,其实和我们平时写的文件操作一样,都是 open() 方法打开文件句柄,然后使用 wb 模式将内容写到文件中。# 源码位置:scrapy/pipelines/files.py# ...class FSFilesStore: # ... def persist_file(self, path, buf, info, meta=None, headers=None): absolute_path = self._get_filesystem_path(path) self._mkdir(os.path.dirname(absolute_path), info) # 保存文件 with open(absolute_path, 'wb') as f: f.write(buf.getvalue()) # ...最后对于 ImagesPipeline 类,其基本处理流程不变,只不过最后的保存方式和普通文件管道不一样,我们来看下面几个方法:# 源码位置:scrapy/pipelines/images.py# ...class ImagesPipeline(FilesPipeline): # ... def file_downloaded(self, response, request, info): return self.image_downloaded(response, request, info) def image_downloaded(self, response, request, info): checksum = None for path, image, buf in self.get_images(response, request, info): if checksum is None: buf.seek(0) checksum = md5sum(buf) width, height = image.size # 保存成图片形式 self.store.persist_file( path, buf, info, meta={'width': width, 'height': height}, headers={'Content-Type': 'image/jpeg'}) return checksum def get_images(self, response, request, info): path = self.file_path(request, response=response, info=info) # 下载的图片内容主体 orig_image = Image.open(BytesIO(response.body)) width, height = orig_image.size if width < self.min_width or height < self.min_height: raise ImageException("Image too small (%dx%d < %dx%d)" % (width, height, self.min_width, self.min_height)) image, buf = self.convert_image(orig_image) yield path, image, buf for thumb_id, size in self.thumbs.items(): thumb_path = self.thumb_path(request, thumb_id, response=response, info=info) thumb_image, thumb_buf = self.convert_image(image, size) yield thumb_path, thumb_image, thumb_buf def convert_image(self, image, size=None): # 图片转换格式 # ... if size: image = image.copy() image.thumbnail(size, Image.ANTIALIAS) buf = BytesIO() image.save(buf, 'JPEG') return image, buf至于上面的代码细节限于篇幅就不再深究了,有兴趣的可以课后去深入学习,这里主要是使用了 Python 的一个专门用来处理图片的第三方模块:PIL。掌握了该模块的基本用法后,再看这些代码就一目了然了,都是非常常规和基础的代码。好了,本小节的内容就到这里了。如果你能坚持看到这里,在回过头看看前面提出的问题,是否在心里都已经有了准确的答案?所有的疑问其实在看一遍源码之后便会豁然开朗,我们也能理解 Scrapy 中设置的参数的含义以及其作用,这些是我们后续深入定制化 Scrapy 框架的基础,一定要掌握。
- 常用的 BOM 相关对象 零基础学习 Javascript
- 08 MySQL 删除数据库 从这里开始学 MySQL 数据库
- MySQL 的事务和隔离级别 深入理解 MySQL 的方方面面
- 微信jssdk-代码演示 一句话介绍
- 5-4 设计消息模块的持久层 在线协同办公小程序
minimize相关搜索
-
mac osx
machine_start
macox
magellan
malloc
manifest
manifest文件
map
map 遍历
mapreduce编程
maps google com
margin
margin bottom
margin left
margin right
margin top
marginbottom
marginheight
marginleft
margintop