54算法实战(三):剖析高性能队列Disruptor背后的数据结构和算法.pdf
《54算法实战(三):剖析高性能队列Disruptor背后的数据结构和算法.pdf》由会员分享,可在线阅读,更多相关《54算法实战(三):剖析高性能队列Disruptor背后的数据结构和算法.pdf(11页珍藏版)》请在文库网上搜索。
1、 | | occurrences | int(11) | YES | | NULL | | +-+-+-+-+-+-+ 虽然表定义的结构变复杂了,但是新增的字段就是 id 字段。它们是整数,不会占用很多空间。另外,每个 URL 和词组都只会储存一次。 除非你安装了第三方包或保存详细的数据库日志,否则你无法掌握数据库里数据增加、更新或删除的具体时间。因此,如果需要对数据可用的空间、变更的频率和变更的重要性进行分析,你应该考虑在 数据新增、更新或删除时加一个时间戳。 5.3.5 MySQL里的里的“六度空间游戏六度空间游戏” 在第 3 章,我们介绍过“维基百科六度分隔”问题,其目标是通过一些词条链
2、接寻找两个词条间的联系(即找出一条链接路径,只要点击链接就可以从一个维基词条到另一个维基词条)。 为了解决这个问题,我们不仅需要建立网络爬虫采集网页(之前我们已经做过),还要把采集的信息以某种形式存储起来,以便后续进行数据分析。 前面介绍过的自增的 id 字段、时间戳以及多份数据表在这里都要用到。为了确定最合理的信息存储方式,你需要先想想游戏规则。一个链接可以轻易地把页面 A 连接到页面 B。同样也可以轻易地把页 面 B 连接到页面 A,不过这可能是另一条链接。我们可以这样识别一个链接,即“页面 A 存在一个链接,可以连接到页面 B”。也就是 INSERT INTO links (fromPa
3、geId, toPageId) VALUES (A, B); (其中,“A”和“B”分别表示页面的 ID 号)。 因此需要设计一个带有两张数据表的数据库来分别存储页面和链接,两张表都带有创建时间和独立的 ID 号,代码如下所示: CREATE TABLE wikipedia.pages ( id INT NOT NULL AUTO_INCREMENT, url VARCHAR(255) NOT NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id); CREATE TABLE wikipedia.
4、links ( id INT NOT NULL AUTO_INCREMENT, fromPageId INT NULL, toPageId INT NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id); 注意,这里和前面打印页面标题的爬虫不同,我没有在页面数据表里使用页面标题字段,为什么这么做呢?其实是因为页面标题要在你进入页面后读取内容才能抓到。那么,如果我们想创建一个高效的 爬虫来填充这些数据表,那么只存储页面的链接就可以保存词条页面了,甚至不需要访问词条页面。 当然并不是所有网站都具有这个
5、特点,但是维基百科的词条链接和对应的页面标题是可以通过简单的操作进行转换的。例如,http:/en.wikipedia.org/wiki/Monty_Python 的后面就是页面标题“Monty Python”。 下面的代码会把“贝肯数”(一个页面与凯文 贝肯词条页面的链接数)不超过 6 的维基百科页面存储起来: from urllib.request import urlopen from bs4 import BeautifulSoup import re import pymysql conn = pymysql.connect(host=127.0.0.1, unix_socket=/
6、tmp/mysql.sock,user= root, passwd=None, db=mysql, charset=utf8) cur = conn.cursor() cur.execute(“USE wikipedia“) def insertPageIfNotExists(url): cur.execute(“SELECT * FROM pages WHERE url = %s“, (url) if cur.rowcount = 0: cur.execute(“INSERT INTO pages (url) VALUES (%s)“, (url) mit() return cur.last
7、rowid else: return cur.fetchone()0 def insertLink(fromPageId, toPageId): cur.execute(“SELECT * FROM links WHERE fromPageId = %s AND toPageId = %s“, (int(fromPageId), int(toPageId) if cur.rowcount = 0: cur.execute(“INSERT INTO links (fromPageId, toPageId) VALUES (%s, %s)“, (int(fromPageId), int(toPag
8、eId) mit() pages = set() def getLinks(pageUrl, recursionLevel): global pages if recursionLevel 4: return; pageId = insertPageIfNotExists(pageUrl) html = urlopen(“http:/en.wikipedia.org“+pageUrl) bsObj = BeautifulSoup(html) for link in bsObj.findAll(“a“, href= pile(“(/wiki/)(?!:).)*$“): insertLink(pa
9、geId, insertPageIfNotExists(link.attrshref) if link.attrshref not in pages: # 遇到一个新页面,加入集合并搜索里面的词条链接 newPage = link.attrshref pages.add(newPage) getLinks(newPage, recursionLevel+1) getLinks(“/wiki/Kevin_Bacon“, 0) cur.close() conn.close() 用递归实现那些需要运行很长时间的代码,通常是一件复杂的事情。在本例中,变量 recursionLevel 被传递到 get
10、Links 函数里,用来跟踪函数递归的次数(每完成一次递归,recursionLevel 就加 1)。当 recursionLevel 值到 5 的时候,函数会自动返回,不会继续递归。这个限制可以防止数据太大导致内存堆栈溢出。 需要注意的是,这个程序可能要运行好几天才会结束。虽然我自己运行过它,但是我的数据库里只保持了一点点贝肯数不超过 6 的词条,因为维基百科服务器会拒绝程序的请求。但是,这些数据对后面 分析维基百水平多关节型机器人 H4系列 机器人手册 Rev.1 C1M13ZR2621R 机器人手册 H4系列 Rev.1 H4 Rev.1 i 水平多关节型机器人 H4系列 机器人手册 R
11、ev.1 Copyright 2013 SEIKO EPSON CORPORATION. All rights reserved. ii H4 Rev.1 前言 感谢您购买本公司的机器人系统。 本手册记载了正确使用机器人所需的事项。 安装该机器人系统前,请仔细阅读本手册与其他相关手册。 阅读之后,请妥善保管,以便随时取阅。 保修 本机及其选装部件是经过本公司严格的质量控制、测试和检查,并在确认性能满足 本公司标准之后出厂交付的。 在交付产品的保修期内,本公司仅对正常使用时发生的故障进行免费修理。 (有关保 修期事项,请咨询您的区域销售办事处。 ) 但在以下情况下,将对客户收取修理费用(即使在保
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 54 算法 实战 剖析 性能 队列 Disruptor 背后 数据结构