[Pikapika]科技文献的脉络梳理-网页展示的编写

基于Flask编写

既然后端数据处理使用了python,最开始的想法是通过python-flask写网页,也因此学习了flask,但是因为实际写后端的时候没有网,于是乎重新回到了自己比较熟悉的nodejs

基于Nodejs编写

网站demo:http://pikapika.mhy12345.xyz:3000

运用d3的数据图形化的库,展示词云与结构树,过程参见http://blog.mhy12345.xyz/2017/05/18/nodejs学习笔记/

词云

使用d3项目https://www.jasondavies.com/wordcloud/,由其中demo的browserify.js生成。

var d3 = require("d3"),
	cloud = require("./utils/d3-cloud");

//var fill = d3.schemeCategory20();
var fill = d3.scaleOrdinal(d3.schemeCategory20);

var layout = cloud()
	.size([500, 500])
	.words(
		JSON.parse(document.getElementById('wordlist').innerHTML)
		.map(function(d) {
			return {text: d[0], size: 10 + d[1], test: "haha"};
		}))
	.padding(1)
	.rotate(function() { return ~~((Math.random()-.5) * 7) * 20; })
	.font("Impact")
	.fontSize(function(d) { return d.size; })
	.on("end", draw);
layout.start();

function draw(words) {
	d3.select(".svg-point").append("svg")
		.attr("width", layout.size()[0])
		.attr("height", layout.size()[1])
		.append("g")
		.attr("transform", "translate(" + layout.size()[0] / 2 + "," + layout.size()[1] / 2 + ")")
		.selectAll("text")
		.data(words)
		.enter().append("text")
		.style("font-size", function(d) { return d.size + "px"; })
		.style("font-family", "Impact")
		.style("fill", function(d, i) { return fill(i); })
		.attr("text-anchor", "middle")
		.attr("transform", function(d) {
			return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
		})
		.text(function(d) { return d.text; });
}

 

结构树

结构树https://bl.ocks.org/mbostock/4063570,直接把里面的js代码搬下来就好了。当然,需要各种修改以适应这里的情况,不过这些细节就不用说了。

var svg = d3.select("svg"),
	width = +svg.attr("width"),
	height = +svg.attr("height"),
	g = svg.append("g").attr("transform", "translate(300,0)");


var stratify = d3.stratify()
	.parentId(function(d) { return d.parentid; });

d3.csv('/tree/'+document.getElementById('infopath').innerHTML+'_t.csv', function(error, data) {
	if (error) throw error;

	var mxdepth = 0;

	root = stratify(data).sort(function(a, b) {return a.id - b.id; });


	d3.cluster().size([height,root.height*200])(root);

	var link = g.selectAll(".link")
		.data(root.descendants().slice(1))
		.enter().append("path")
		.attr("class", function(d){ return d.children?"link":"link-leaf";})
		.attr("d", function(d) {
			if (!d.children)
				return "M" + d.y + "," + d.x
					+ "C" + (d.parent.y + 100) + "," + d.x
					+ " " + (d.parent.y + 100) + "," + (d.x+d.parent.x)/2
					+ " " + d.parent.y + "," + d.parent.x;
			else
				return "M" + d.y + "," + d.x
					+ "C" + (d.parent.y + 100) + "," + d.x
					+ " " + (d.parent.y + 100) + "," + d.parent.x
					+ " " + d.parent.y + "," + d.parent.x;
		});

	var node = g.selectAll(".node")
		.data(root.descendants())
		.enter().append("g")
		.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
		.attr("transform", function(d) { return d.children?
				"translate(" + d.y + "," + d.x + ")" :
				"translate(" + d.y + "," + d.x + ")"; });

	node.append("circle")
		.attr("r", 2.5);

	node.append("text")
		.style('font-size',13)
		.attr("dy", 3)
		.attr("x", function(d) { return d.children ? -8 : 8; })
		.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
		.text(function(d) {return d.data.text });
});

 

Nodejs学习笔记

相关链接

Express

Express官网:http://www.expressjs.com.cn

DC3

DC3官网:https://d3js.org

DC3 tutorials:https://github.com/d3/d3/wiki/Tutorials

选择器原理:https://bost.ocks.org/mike/join/

D3 4.0 API:https://github.com/d3/d3/blob/master/API.md

browserify

官网:http://browserify.org

D3-cloud词云制作

d3-scale-category20 undefined:http://stackoverflow.com/questions/41178111/d3js-d3-scale-category10-not-working

Jade

教程1:http://www.w3cplus.com/html/how-to-use-jade.html

Nodejs 包

Child_process:http://nodejs.cn/api/child_process.html

[Pikapika]科技文献的脉络梳理-构建查询Wiki的数据结构

首先我们需要实现的是一个能够查询Wiki的数据结构,而有如下几种处理方式

  1. 直接的爬虫抓取及其优化
  2. 调用现成python库(基于wiki的api)
  3. 下载离线版wikipedia

直接使用爬虫抓取wikipedia

如果直接使用python的urllib库调用的话,由于网络延迟等问题,效率大概是3sec/search

这里粘贴一个爬取百度百科的代码,wiki可以肯定比百度百科慢,毕竟在墙外面……

# -*- coding:utf-8 -*-
import urllib2
import re
import cgi
import time
import requests
import random
import httplib
from bs4 import BeautifulSoup


ip_update = -1
ip_list = []

def get_ip_list():
    url = 'http://www.xicidaili.com/nn/';
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
    }
    web_data = requests.get(url, headers=headers)
    soup = BeautifulSoup(web_data.text, 'lxml')
    ips = soup.find_all('tr')
    global ip_list
    ip_list = []
    for i in range(1, len(ips)):
        ip_info = ips[i]
        tds = ip_info.find_all('td')
        ip_list.append(tds[1].text + ':' + tds[2].text)
    print "IP list updated ..."
    print ip_list

def get_random_ip():
    global ip_update
    global ip_list
    if (ip_update < 0):
        get_ip_list()
        ip_update = 100
    else:
        ip_update -= 1
    proxy_list = []
    for ip in ip_list:
        proxy_list.append('http://' + ip)
    proxy_ip = random.choice(proxy_list)
    return proxy_ip

def open_url(url,enable_proxy=True):
        #ip = get_random_ip()
        ip = '180.76.154.5:8888'
        print url
        print "Process url " + '...' + " with proxy " + ip
        proxy_handler = urllib2.ProxyHandler({"http" : ip})
        null_proxy_handler = urllib2.ProxyHandler({})
        if enable_proxy:
            opener = urllib2.build_opener(proxy_handler)
        else:
            opener = urllib2.build_opener(null_proxy_handler)
        urllib2.install_opener(opener)
        i_headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8'}
        req = urllib2.Request(url,headers=i_headers)
        time.sleep(0.5)
        try:
            print "Sleepp....."
            html = urllib2.urlopen(req)
            print "Sleepp....."
            if (not html.geturl() == url):
                print "Warning: URL redirected..."
            return html
        except httplib.BadStatusLine:
            print "ERROR"
            return None
        except urllib2.URLError:
            print "Error: URLERROR"
            return open_url(url,enable_proxy)



if __name__ == '__main__':
    fin = open('keywords_output.txt','r')
    lst = fin.read().split('\n')
    fout = open('keywords_ranking.txt','w')
    lst = lst[0:-2]
    for w in lst:
        res = open_url('https://baike.baidu.com/item/%s'%(w))
        if (res == None):
            fout.write("--\n")
            continue
        text = res.read()
        for ww in lst:
            print ww,len(re.findall(ww,text)),
            fout.write(str(len(re.findall(ww,text)))+'\t')
        fout.write('\n')
        time.sleep(1)
        print ;

 

接着考虑使用更加高效的爬取框架scrapy

代码架构比较复杂,但是搜索的速度可以提升至1sec/search,其原理大概是通过异步的方式解决网络延迟的问题,但是基础的长达3sec的网络延迟还是必定会存在的,不过对于我们的分析还是过于慢了

Python库实现wiki查询

python有一个叫做wikipedia的库,其核心是通过wikipedia的公开api实现查询。还是很慢……

离线Wiki数据查询

离线数据下载主页:https://en.wikipedia.org/wiki/Wikipedia:Database_download

具体来说我下载的离线数据在这里:https://dumps.wikimedia.org/other/static_html_dumps/current/zh/

其中html.lst文件列举了所有文件名,wikipedia-zh-html.tar.7z文件就是实际的数据集,解压后11G,最棒的是解压后发现居然已经帮我把trie树建出来了!

但是,问题来了,虽然在个人的mac上面文件名非常正常,但是把它弄到ubuntu下面就完全不可看,大概就是一堆问号的情况。事实上这只是ssh上去的显示问题,还是可以用程序访问的。

不过速度嘛……

[Pikapika]科技文献的脉络梳理-概述

离散大作业我和wxz希望能够做一个科技文献的脉络梳理的小程序,输入一篇科技文献(可以是html或者纯文本),通过关键词查询等方式实现文献脉络的整理。

其中我们计划的是通过pagerank算法,引入wiki外部语料库建模,提取出科技文献的脉络。

实际上,由于效率的问题,我们并没有使用wiki外部资料库,单纯使用了pagerank。

而demo的展示通过网页实现:http://pikapika.mhy12345.xyz:3000,不过我并不准备长时间维护这个网站,所以说上不去很正常……

人智大作业-四子棋实验报告

题目大意

带重力的四子棋(连成4个(横竖斜)胜利)

大致算法

预测:朴素搜索

通过判定一个必胜态的后继状态存在对手必败态,一个必败态后继状态必须全是对手必胜态。实现搜索算法,搜索深度可以达到6层左右。

朴素搜索只能对于短期一定必胜、必败的状态进行判断,故可用于

  1. 蒙特卡罗树新增一个节点时,如果该节点胜负短期可判,则不使用随机游走,而直接将固定胜率\败率100%返回
  2. 决策时跑预测防止出现一些蒙特卡洛故意走向一个必败态的情况

估值:随机下子

估计一个局面的情况可以通过随机下子的方式,双方随机在可能的位置等概率下子,判断最后谁胜,将随机下子次数增加可以非常“不准确”的估计出当前局面对谁有优势

决策:蒙特卡洛搜索树

对于上述算法,在短期无法判断局面的时候很难决策如何下子,因此使用信心上限树算法(UCT).

     $$I_j = X_j + \sqrt{\frac{2ln(n)}{T_j(n)}}$$

通过上面的式子得出决策树上每一个位置的信心上限[latex]I_j[\latex],其中n表示总的尝试次数,

    \[$T_j$\]

表示第j个状态(及其子状态)尝试次数。

显然,每次尝试I值最大的状态可以平衡所有状态的最小尝试次数以及对较优状态的多次尝试。

程序表现

与样例程序进行对抗,分数大约在30/200分左右。

一些细节

  1. 蒙特卡洛树的决策最好选择访问次数最多的而非期望权值最大的那一个,因为蒙特卡洛每次都会拓展期望权值L最大的那一个,并有一定概率使其变小。换句话说,蒙特卡洛的决策在某种意义下就是平衡L值得过程,所以L值并不能代表一个状态的优劣
  2. 比较神奇的是有些时候迭代次数较多的程序表现没有迭代次数较少的程序,可能是因为常数没有调好……
  3. 曾经尝试在随机游走的时候加入深度较小的特判,使得双方“稍微”有一点智能,但是发现这样会导致结果基本是平局
  4. 最开始程序使用new分配内存,然而Compete程序多次调用会出现segmentation fault,单独调用无误,改为预先分配就没有问题了。不知道是否和电脑的垃圾回收机制有关系。

makefile学习笔记&C++编译

静态链接库创建

  1. ar -rv maze.a BaseRouter.o ,将BaseRouter.o加入maze.a这个静态链接库中
  2. ranlib maze.a ,更新静态链接库符号表
  3. 库文件一般将.cpp改成.cxx

makefile笔记

  1. .PHONY: clean  表示clean为伪目标,否则如果文件夹下有clean文件会出错
  2. 而命令中的<</span> 和<span class="lang:default decode:true crayon-inline ">@ 则是自动化变量,<</span> 表示所有的依赖目标集(也就是<span class="lang:default decode:true crayon-inline ">BaseRouter.cxx</span> ),<span class="lang:default decode:true crayon-inline ">@ 表示目标集(就是BaseRouter.o ),参见样例1
  3. makefile在target为.o的时候,dependence可以自动省略.cc,可以使用类似于main.o : defs.h 的语法
  4. makefile只会完成第一个规则的第一个目标
  5. (objects)</span> 只是单纯的变量展开,一般表现为多条命令都是由于多目标的生成</li> </ol> <h3>样例</h3> <h4>OOPWeek9_Makefile</h4> <pre class="lang:default decode:true" title="makefile">lSOURCES=(wildcard *.cxx)
    sSOURCES=(wildcard *.cpp) HEADERS=(wildcard *.h)
    lOBJECTS=(lSOURCES:%.cxx=%.o) sOBJECTS=(sSOURCES:%.cpp=%.o)
    TARGET=maze.exe
    LIB=maze.a

    all: (TARGET)(LIB)
    (TARGET):(sOBJECTS) (HEADERS)(LIB)
    @echo “Now Generating (TARGET) ..." 	g++(sOBJECTS) (LIB) -o(TARGET)
    (LIB):(lOBJECTS) (HEADERS) 	@echo "Now Generating(LIB) …”
    ar -rv (LIB)(lOBJECTS)
    ranlib (LIB) %.o: %.cpp(HEADERS)
    @echo “Now Compiling < ..." 	g++ -c< -o @ %.o: %.cxx(HEADERS)
    @echo “Now Compiling < ..." 	g++ -c< -o @ clean: 	rm *.o *.exe *.bak *.a explain: 	@echo "Lib Sources:(lSOURCES)”
    @echo “User Sources: (sSOURCES)" 	@echo "Lib Objects:(lOBJECTS)”
    @echo “User Objects: (sOBJECTS)" 	@echo "Lib:(LIB)”
    @echo “Target: $(TARGET)”

    BaseRouter.cxx	BaseRouter.h	OptRouter.h	main.cpp	makefile

     

滚蛋吧,肿瘤君

随想

之前在飞机上看了一半,然后飞机就落地了……当时的感觉就是好电影,但是比较懒,不想之后去补后面一半。今天没事干才翻出来看完了,真是少有的好电影。

不过看豆瓣评分,随随便便的一个大场面电影都能够踩这种感情向电影,也许现在的人确实是太浮躁了。不过在我心中,好的电影终究是好的,并不需要在意别人对它的评分高低。

虽然说这部作品让我意识到在自己挥霍青春之时,有不少人正在与死神争分夺秒。但是,又如何才算是有意义的生活呢?正如电影里的艾米,她的生活究竟有没有意义?这种哲学的问题单靠想象根本无从回答,或许从来就没有答案吧。

摘录

听一场摇滚,和耳朵一起一醉方休;喝一圈烈酒,让酒腻子们闻风丧胆;开一场cosplay party,二次元万岁;摸一下大蜥蜴,我熊胆威风凌厉;吃三斤驴打滚,翻滚吧肠胃;飚一把摩托车,成为风驰电掣的女王;见一下微博红人,感受马伯庸亲王的慈祥;至少学会一样乐器,为喜欢的人弹;种一次昙花,守望者它盛开;做一桌丰盛的晚餐给爸妈,哪怕色不香,味不美;来一次夜钓,吸取月光静臆的能量;仰望喀纳斯的星空,寻找属于我的星座;沐浴漠河的极光,感受它的神秘;去山顶看一次日出,然后大喊滚蛋吧肿瘤君。

种一次昙花,守望着它盛开,这句话真的太美了。现在的我,真的会这样为了一朵花,静静等待一个晚上吗?真的能够下定决心,到一个不被城市灯光污染的地方,欣赏宁静的月色?

真正的朋友就像健康,只有当失去的时候才知道他们的珍贵。

羡慕

人活在想象世界里,其实是一件很美好的事情,没有恐惧、没有忧愁、也不会有死亡。

 

人不能因为终归会死,就不想活了。
所以不能因为害怕失去,就不去拥有。
爱与被爱,是这个世界上最重要的事情。

四月读书记录

《外星人防御计划》,读完,比较有意思的一本书,讲的就是各种地外生命的探测理论等,半年前开坑,看了一大半然后忘掉了????,这个月翻出来看完了

《白说》,50%,到后面没有前面好看了……

《雪国》,15%,月底开的坑

《人类简史》,5%,看了样章,还不错,等学生会送的实体书……