BOP 2016 SEMI 结束之结束 2

挖一个大坑,我是来观光的。

坑还没填完。

BOP 2016 SEMI Rank#11 团队 yaoyao 代码。

基于 Python 2.7 ,使用 flask 提供 Web API 终结点。665行的人生。

使用的库

REST API 入口: cca

求解主入口: get_all_possible_ans

cca

[挖坑]

get_all_possible_ans

与 Elecky 类似,在查询 Id 类型的同时,将作者的所有论文全部下载下来,然后判断节点对的类型,分别使用 get_Id_Id 、 get_AuId_Id 、 get_Id_AuId 和 get_AuId_AuId 子过程解决问题。

get_entity

#167:这就是“同一查询,两次请求”的实现。注意到 get_entity_one 会将下载下来的论文信息放到 q 中。

#170:只是为了等待其它的 greenlet 。目前使用的都是默认值(空)。

#171:注意到线程安全队列的 Queue.get 在队列为空时会阻塞调用方。此处十分巧妙地利用了这一特点,如果 t_l 中有任意一次请求先完成,那么阻塞就会解除,  ans 马上被赋值。

加速的方法:3.一个语句同时查询两次(单次查询时间波动较大,两次查询同时进行,并且使用先返回的结果,会更稳定) [1]

随后就是 JSON 解析和返回了。

#176:可能作者也觉得强行 socket (参阅下文)有点丧心病狂,所以如果在用 socket 的时候出现任何问题,就回退到 get_ans_http ,使用 httplib.HTTPConnection (对应 Python 3 的 http.client.HTTPConnection )进行连接。

get_ans

其中, para 是一个字典,包含了URL请求的查询属性和值; i 不知道是干什么的,可能是之前向控制台输出以区分 get_entity 的两次连接的。

#95:socket pool 不多说。

加速的方法: 1.socket 长连接 [1]

#99:将字典转换为完整的 URL 。

#101:好吧,强行 socket

requests > urllib2 >httplib > socket长连接 时间消耗依次减少 [1]

那么先把 HTTP 1.1 完整的请求和回复放在这里备用吧。例如

#105, #113:注意 socket.recv 是阻塞函数。不过前面的调用方基本上都是在工作线程调用此函数的,所以也就无谓了。

#106-#109:为了从回复中套出 Content-Length 标头的值。

#113:随后就可以开始愉快地接收数据了。缓冲区大小 8KB 。

数据收完之后就可以返回了。

#123:在程序一开始运行的时候,就向池中填满新鲜的 sockets 。

heart_beat

在此函数中生成了一个简单的请求,然后把 s_q socket 池中的 socket 取出来,一个一个地使用 get_ans 向外发送请求。函数保证了每一个 socket 在一分钟内会被使用一次。

然而这里的 start 被注释掉了……什么状况……

get_Id_Id

与 Elecky 类似,如果  Id2 的被引次数大于1000,则使用 get_Id_Id 从左向右搜索;否则使用 get_Id_Id_CC 从右向左搜索。

这里 Id1_en 、 Id2_en 分别对应了 Id1 、 Id2 的论文详细信息。

对于从左向右搜索的情况

#266:先把 Id1 引用的所有文献(潜在的 Id3 )下载下来,存入 Id1_RId_en_l 中,然后按顺序考虑以下情况

Id1 - AuId/FId/CId/JId3 - Id4 - Id2 (分支):构造查询表达式

查找(包含 Id1.AuId/FId/JId/CId
或位于 Id3.RId 列表中)且引用了 Id2 的论文

很明显,这就是为了查找 Id4 。顺带一提, Or_expr_Id 实现了按照允许的最大表达式长度对查询进行拆分的功能。

#275:作者应该是 JId/CId 不分的,统统称为 CId

#286:然后把拆分后的查询表达式丢给 gevent.spawn ,在工作线程中进行下载。

Id - Id :这个很明显。

Id1 - Id3 - Id2 :在 Id_RId_Id 子过程中,由于此时已经把所有可能的 Id3 下载下来了,所以直接判断其 RId 中是否包含 Id2 即可。

Id1 - CId/JId/FId/AuId3 - Id2 :这个也很明显。

Id1 - Id3 - CId/JId/FId/AuID4 - Id2 :这个也很明显,考虑到所有的 Id3 都被下载下来了。

Id1 - AuId/FId/CId/JId3 - Id4 - Id2 (汇合):等待前面 spawn 出来的线程工作完毕,然后查一下返回的 Id4 论文的属性,就可以一条一条地返回了。

对于从右向左搜索的情况

 

[未完待续]

发布者

CXuesong

CXuesong

给我一点点考虑的时间。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*