Python网络数据采集.pdf
《Python网络数据采集.pdf》由会员分享,可在线阅读,更多相关《Python网络数据采集.pdf(80页珍藏版)》请在文库网上搜索。
1、们就将这个新数据插入到 小顶堆。 这个时候就有可能出现,两个堆中的数据个数不符合前面约定的情况:如果n是偶数,两个堆中的数据个数都是$fracn2$;如果n是奇数,大顶堆有$fracn 2+1$个数据,小顶堆有$fracn2$个数据。这个时候,我们可以从一个堆中不停地将堆顶元素移动到另一个堆,通过这样的调整,来让两个堆中的数据满足上 面的约定。 29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 于是,我们就可以利用
2、两个堆,一个大顶堆、一个小顶堆,实现在动态数据集合中求中位数的操作。插入数据因为需要涉及堆化,所以时间复杂度变成 了O(logn),但是求中位数我们只需要返回大顶堆的堆顶元素就可以了,所以时间复杂度就是O(1)。 29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 实际上,利用两个堆不仅可以快速求出中位数,还可以快速求其他百分位的数据,原理是类似的。还记得我们在“为什么要学习数据结构与算法”里的这个问题 吗?“如何快
3、速求接口的99%响应时间?”我们现在就来看下,利用两个堆如何来实现。 在开始这个问题的讲解之前,我先解释一下,什么是“99%响应时间”。 中位数的概念就是将数据从小到大排列,处于中间位置,就叫中位数,这个数据会大于等于前面50%的数据。99百分位数的概念可以类比中位数,如果将一组数据 从小到大排列,这个99百分位数就是大于前面99%数据的那个数据。 如果你还是不太理解,我再举个例子。假设有100个数据,分别是1,2,3,100,那99百分位数就是99,因为小于等于99的数占总个数的99%。 弄懂了这个概念,我们再来看99%响应时间。如果有100个接口访问请求,每个接口请求的响应时间都不同,比如
4、55毫秒、100毫秒、23毫秒等,我们把这100个接 口的响应时间按照从小到大排列,排在第99的那个数据就是99%响应时间,也叫99百分位响应时间。 我们总结一下,如果有n个数据,将数据从小到大排列之后,99百分位数大约就是第n*99%个数据,同类,80百分位数大约就是第n*80%个数据。 弄懂了这些,我们再来看如何求99%响应时间。 我们维护两个堆,一个大顶堆,一个小顶堆。假设当前总数据的个数是n,大顶堆中保存n*99%个数据,小顶堆中保存n*1%个数据。大顶堆堆顶的数据就是我们要 找的99%响应时间。 每次插入一个数据的时候,我们要判断这个数据跟大顶堆和小顶堆堆顶数据的大小关系,然后决定插
5、入到哪个堆中。如果这个新插入的数据比大顶堆的堆顶数据 小,那就插入大顶堆;如果这个新插入的数据比小顶堆的堆顶数据大,那就插入小顶堆。 但是,为了保持大顶堆中的数据占99%,小顶堆中的数据占1%,在每次新插入数据之后,我们都要重新计算,这个时候大顶堆和小顶堆中的数据个数,是否还符 合99:1这个比例。如果不符合,我们就将一个堆中的数据移动到另一个堆,直到满足这个比例。移动的方法类似前面求中位数的方法,这里我就不啰嗦了。 通过这样的方法,每次插入数据,可能会涉及几个数据的堆化操作,所以时间复杂度是O(logn)。每次求99%响应时间的时候,直接返回大顶堆中的堆顶数据即 可,时间复杂度是O(1)。
6、29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 解答开篇 学懂了上面的一些应用场景的处理思路,我想你应该能解决开篇的那个问题了吧。假设现在我们有一个包含10亿个搜索关键词的日志文件,如何快速获取到Top 10最热门的搜索关键词呢? 处理这个问题,有很多高级的解决方法,比如使用MapReduce等。但是,如果我们将处理的场景限定为单机,可以使用的内存为1GB。那这个问题该如何解决呢? 因为用户搜索的关键词,有很多可
7、能都是重复的,所以我们首先要统计每个搜索关键词出现的频率。我们可以通过散列表、平衡二叉查找树或者其他一些支持快 速查找、插入的数据结构,来记录关键词及其出现的次数。 假设我们选用散列表。我们就顺序扫描这10亿个搜索关键词。当扫描到某个关键词时,我们去散列表中查询。如果存在,我们就将对应的次数加一;如果不存 在,我们就将它插入到散列表,并记录次数为1。以此类推,等遍历完这10亿个搜索关键词之后,散列表中就存储了不重复的搜索关键词以及出现的次数。 然后,我们再根据前面讲的用堆求Top K的方法,建立一个大小为10的小顶堆,遍历散列表,依次取出每个搜索关键词及对应出现的次数,然后与堆顶的搜索关键 词
8、对比。如果出现次数比堆顶搜索关键词的次数多,那就删除堆顶的关键词,将这个出现次数更多的关键词加入到堆中。 以此类推,当遍历完整个散列表中的搜索关键词之后,堆中的搜索关键词就是出现次数最多的Top 10搜索关键词了。 不知道你发现了没有,上面的解决思路其实存在漏洞。10亿的关键词还是很多的。我们假设10亿条搜索关键词中不重复的有1亿条,如果每个搜索关键词的平均长 度是50个字节,那存储1亿个关键词起码需要5GB的内存空间,而散列表因为要避免频繁冲突,不会选择太大的装载因子,所以消耗的内存空间就更多了。而我们 的机器只有1GB的可用内存空间,所以我们无法一次性将所有的搜索关键词加入到内存中。这个时
9、候该怎么办呢? 我们在哈希算法那一节讲过,相同数据经过哈希算法得到的哈希值是一样的。我们可以哈希算法的这个特点,将10亿条搜索关键词先通过哈希算法分片到10个文 件中。 具体可以这样做:我们创建10个空文件00,01,02,09。我们遍历这10亿个关键词,并且通过某个哈希算法对其求哈希值,然后哈希值同10取模,得到的 结果就是这个搜索关键词应该被分到的文件编号。 对这10亿个关键词分片之后,每个文件都只有1亿的关键词,去除掉重复的,可能就只有1000万个,每个关键词平均50个字节,所以总的大小就是500MB。1GB的 内存完全可以放得下。 我们针对每个包含1亿条搜索关键词的文件,利用散列表和堆
10、,分别求出Top 10,然后把这个10个Top 10放在一块,然后取这100个关键词中,出现次数最多的10个 关键词,这就是这10亿数据中的Top 10最频繁的搜索关键词了。 内容小结 我们今天主要讲了堆的几个重要的应用,它们分别是:优先级队列、求Top K问题和求中位数问题。 优先级队列是一种特殊的队列,优先级高的数据先出队,而不再像普通的队列那样,先进先出。实际上,堆就可以看作优先级队列,只是称谓不一样罢了。求Top K问题又可以分为针对静态数据和针对动态数据,只需要利用一个堆,就可以做到非常高效率的查询Top K的数据。求中位数实际上还有很多变形,比如求99百分 位数据、90百分位数据等
11、,处理的思路都是一样的,即利用两个堆,一个大顶堆,一个小顶堆,随着数据的动态添加,动态调整两个堆中的数据,最后大顶堆的 堆顶元素就是要求的数据。 课后思考 29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 有一个访问量非常大的新闻网站,我们希望将点击量排名Top 10的新闻摘要,滚动显示在网站首页banner上,并且每隔1小时更新一次。如果你是负责开发这个功 能的工程师,你会如何来实现呢? 欢迎留言和我分享,我会第
12、一时间给你反馈。 精选留言: 29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 feifei 2018-12-02 08:48:11 有一个访问量非常大的新闻网站,我们希望将点击量排名 Top 10 的新闻摘要,滚动显示在网站首页 banner 上,并且每隔 1 小时更新一次。如果你是负责开 发这个功能的工程师,你会如何来实现呢? 我的思路是这样子, 1,对每篇新闻摘要计算一个hashcode,并建立摘要与hash
13、code的关联关系,使用map存储,以hashCode为key,新闻摘要为值 2,按每小时一个文件的方式记录下被点击的摘要的hashCode 3,当一个小时结果后,上一个小时的文件被关闭,开始计算上一个小时的点击top10 4,将hashcode分片到多个文件中,通过对hashCode取模运算,即可将相同的hashCode分片到相同的文件中 5,针对每个文件取top10的hashCode,使用Map的方式,统计出所有的摘要点击次数,然后再使用小顶堆(大小为10)计算top10, 6,再针对所有分片计算一个总的top10,最后合并的逻辑也是使用小顶堆,计算top10 7,如果仅展示前一个小时的t
14、op10,计算结束 8,如果需要展示全天,需要与上一次的计算按hashCode进行合并,然后在这合并的数据中取top10 9,在展示时,将计算得到的top10的hashcode,转化为新闻摘要显示即可 老师,你讲的这些例子,我觉得对我的工作和学习很有帮助,于是我花了一个周末将这一章节,将你所讲的堆的应用示例,全部翻译成了代码,并做了相关 的验证,感觉自己收获很多,我也将这块代码上传了github,欢迎老师你的指正,需要的同学,也可以一起交流, 1,合并有序小文件 2,高性能定时器的应用 3,求topk 4,求中位数 5 ,大文件的关键字的统计 31赞 Miletos 2018-11-27 23
15、:47:43 “如果新加入的数据小于等于大顶堆的堆顶元素,我们就将这个新数据插入到大顶堆;如果新加入的数据大于等于小顶堆的堆顶元素,我们就将这个新数据 29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 插入到小顶堆。” 1. 这里不太对劲,前文中说到,小顶堆的堆顶大于大顶堆的堆顶。 如果新进元素在小顶堆堆顶和大顶堆堆顶元素值之间,没有规定插入哪个堆。 我觉得,是不是只要判断一次就可以了。新进元素值大于等于小顶堆堆顶
16、元素的,插入小顶堆,否则插入大顶堆。 当某一个堆数据过多时再重新移动堆顶元素。 2. 求中位数的源数据中,是否允许重复数据? 25赞 作者回复2018-11-28 11:08:48 1 你说的对 我改下 多谢指正 2 可以重复 豪华 2018-11-28 00:14:20 老师,分片求取前十是不是有bug,如果有一个关键词在每一组分片中都是前第十一位,在整个十亿中个数总和是第一位,是不是用分片求出了错误的结果 呢? 9赞 作者回复2018-11-28 01:58:31 不会的 相同的关键词经过哈希之后只会到一台机器 守着云开 2018-11-28 09:20:27 10亿关键词分片之后 每个文
17、件并不一定有1亿的关键词吧 老师 7赞 蔷薇骑士 2018-12-14 11:35:12 定时任务这个例子感觉有问题吧,定时任务是动态加入的,假设当前堆顶的任务是一个小时后的,难道这一个小时都不做扫描吗,随时可能会加入需要更早 执行的任务 6赞 辉哥 2018-12-02 03:49:37 思考题:1,维护两个散列表,一个是一小时新增的点击量的散列表,以新闻id为键,点击次数为值。一个是全部点击量的散列表。每隔一小时把新增的散列 表的数据同步到全部点击量的散列表。然后把这小时内有变化的全部点击量的散列表的数据(即此小时有新增点击量的新闻数据)和我们维护的10个元素小 顶堆堆顶进行比较,比堆顶的
18、点击量大的,则使用该元素替换堆顶,再进行堆化。比堆顶点击量小的则不做处理。然后比较完,根据堆顶的10个元素的id, 从数据库读取相应的新闻摘要显示在banner上。除此之外,还要把变化后的全部点击量散列表同步到数据库。因为保存的是新闻id,所以散列表长度不会很 大,所占用的内存也不会很大。而每个小时新增的访问量的新闻id数也不会很多,毕竟很多人只会阅读热门消息。所以新增的点击量的新闻数据假设为k,则 每小时同步小顶堆的时间负责度为o(klg 10); 4赞 29|堆的应用:如何快速获取到Top10最热门的搜索关键词? file:/F/temp/geektime/数据结构与算法之美/29堆的应用
19、:如何快速获取到Top10最热门的搜索关键词?.html2019/1/15 15:36:04 ALAN 2018-11-28 11:15:14 1:建一个散射列表,key为点击网址,value为点击次数。散射列表通过从log中计算得来。 2:建一个10个数据的小顶堆,数据值为点击次数,扫描散射列表,新元素次数比堆顶元素大则删除堆顶元素,插入新元素,小则继续扫描散射列表。 3:扫描完整个散射列表后,即得到top 10点击量,将点击网址存储在数组A中。数组A一个小时更新一次。 4:散射列表实时更新,小顶堆也实时更新,以一小时为间隔,将小顶堆结果更新到数组A中。 4赞 oatlmy 2018-11-
20、28 04:41:50 老师,请问为什么评价算法性能是根据时间和空间复杂度,而不是别的参数?是因为计算机结构是冯诺依曼体系,除了输入输出设备和控制器,就剩下运算 器和存储器了吗? 3赞 作者回复2018-11-28 11:17:24 你理解的没错 小新是也 2018-12-09 14:23:25 如果我要1%到99%响应时间,这样建的堆就有点多了 2赞 作者回复2018-12-10 01:56:00 这需求.具体问题具体分析吧 geektime learn 2018-11-28 02:19:14 Hadoop、Spark入门demowordcount了解下 2赞 S(PMOS)管导通, 不会形
21、成电源到地的直流通路. (至于防止静电造成损坏, 因芯片管脚设计中一般会加保护电路, 反而无此必要).2. 对于输出管脚:1)正常的输出管脚(push-pull型), 一般没有必要接上拉或下拉电阻.2)OD或OC(漏极开路或集电极开路)型管脚,这种类型的管脚需要外接上拉电阻实现线与功能(此时多个输出可直接相连. 典型应用是: 系统板上多个芯片的INT(中断信号)输出直接相连, 再接上一上拉电阻, 然后输入MCU的INT引脚, 实现中断报警功能).其工作原理是: 在正常工作情况下, OD型管脚内部的NMOS管关闭, 对外部而言其处于高阻状态, 外接上拉电阻使输出位于高电平(无效中断状态); 当有
22、中断需求时, OD型管脚内部的NMOS管接通, 因其导通电阻远远小于上拉电阻, 使输出位于低电平(有效中断状态). 针对MOS 电路上下拉电阻阻值以几十至几百K为宜.儀儀事不抓住主要问题,而专顾细枝末节。3、对科学精神的其他认识:尊重事实、一丝不苟、敢于质疑、不断创新更多免费资料,请关注公众号:阅乐课堂20|散列表(下):为什么散列表和链表经常会一起使用? file:/F/temp/geektime/数据结构与算法之美/20散列表(下):为什么散列表和链表经常会一起使用?.html2019/1/15 15:35:45 20|散列表(下):为什么散列表和链表经常会一起使用? 我们已经学习了20节
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Python 网络 数据 采集