dlist相关知识
-
Android线程通信进程(Process)通常表现为一个正在运行的应用程序实体,在默认情况下,每个正在运行的应用程序有且只有1个进程 线程(Thread)是计算机进行调度的基本单位,表现为进程中某个单一顺序的控制流,它可以被认为是一个轻量级的进程(LightWeightProcess) 同一进程中可以有若干个线程 ANR:应用程序无响应 在子线程中更新UI的方法: Activity类: public void RunOnUiThread(Runnable action) View类: public boolean post(Runnable action) //方法二 public boolean postDelayed(Runnable ac
-
面试题数据结构学习笔记数据结构是的大二时候学的,后来做项目的时候感觉其实应用的还挺多的,不过除了常用的基本上也都忘得差不多了,好好复习复习,查漏补缺。链表与数组数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,这个编号叫做下标,我们可以通过下标来区别这些元素。数组元素的个数有时也称之为数组的长度。数组在内存中是逐个存放的,也就是说倘若数组的第一个元素在地址A,则数组第二个元素就在地址A+1。而链表则不是,链表每个节点没有相对固定的位置关系。某个节点在地址A其后的节点不一定是A+1,而在内存的其他空闲区域,呈现一种随机的状态。数组一旦显式的被申明后,其大小就固定了,不能动态进行扩充。而链表则可以,可以动态生成节点并且添加到已有的链表后面。链表灵活,但是空间和时间额外耗费较大;数组大小固定,元素位置固定,但是操作不灵活,且容易浪费空间,但是时间耗费较小,尤其是元素变化不大的时候效率很高。双向链表比单向的更灵活,但是空间耗费也更大链表的特性是在中间任意位置添加删除元素的都非常的快,不需要移动其
-
让css3动画变得有趣wowjswowjs可以在网页滚动时, 展示css动画,是animater的好朋友, wowjs官方实例演示链接: https://mynameismatthieu.com/WOW/animate.css 包含了一组炫酷、有趣、跨浏览器的动画,可以在你的项目中直接使用。使用方法1. 在页面头部引入, animate.css和wow.js, cdn地址如下:<link href="https://cdn.bootcss.com/animate.css/3.5.2/animate.min.css" rel="stylesheet"><script src="https://cdn.bootcss.com/wow/1.1.2/wow.min.js"></script>2. 在需要添加动画的html元素上, 新增两个类属性, 第一个为wow, 第二个为动画名如从左侧滑入slideInLeft<p class="wo
-
我的梦想之门射入了一道光我是潜在悟空:本人2011年毕业,一直在一家新能源厂家工作,从事工艺后来又转向现在的品质。在做品质期间升了职,对现在中国制造业质量管理的现状有了更加清晰明了的认知。认清的同时就是失望和迷茫,中国制造业粗放式的增长,但品质管理精细化,生产运营规范化都觉得还有很大的差距。由于普遍的公司高层对品质认知的误差导致品质从业人员处在一个非常尴尬的位置。品质总监也成为阵亡率极高的一个位置。想要生存,需要耗费大量技术之外的精力。而这种技术之外的事物让我窒息。另外一个很重要的情况是我刚结婚,马上面临要孩子的事情。孩子出生后,我还有多大的精力去拼现在的工作。如果拼技术还好说,可是90%的精力都是在技术的外围。不!这不是我想要的生活,这不是我想要的人生!!!由于不满足现状,我开始在寻求解决方案。大的方向就是我要跳出制造业,跳出车间。我上大学时我的专业是日语,C语言是周围同学都不感兴趣的课,而我却大爱。我明白对计算机、互联网有着浓烈的兴趣和热爱。且做品质的是离不开数分析的,质量管理体系的八大原则之一是基于事实的决策,而事实就是数据
dlist相关课程
dlist相关教程
- 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 框架的基础,一定要掌握。
- 校园招聘 校招&社招后端高频面试题核心回答及思路解析
- 4-9 剖析Kubeadm安装原理 Kubernetes从入门到进阶实践
- 消息发送模式实战之发布订阅模式 一只可爱的小兔把你代入大厂
- 11 SQL NULL SQL 程序员的必学技能
- VueRouter 路由嵌套 零基础入门 Vue 开发
dlist相关搜索
-
daima
damain
dart
dataset
datasource
datediff
datediff函数
datepicker
datetime
db4o
dbi
dcloud
deallocate
debian安装
debugger
debugging
declaration
declarations
declare
decode函数