<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>鬼の领地 &#187; Python</title>
	<atom:link href="http://blog.upsuper.org/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.upsuper.org</link>
	<description>the place where there are some ghost appearing...</description>
	<lastBuildDate>Wed, 19 Oct 2011 13:21:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>关于饭否的两个小脚本</title>
		<link>http://blog.upsuper.org/two-scripts-for-fanfou/</link>
		<comments>http://blog.upsuper.org/two-scripts-for-fanfou/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 04:06:24 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[饭否]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=1197</guid>
		<description><![CDATA[前几天因为某些原因，我把饭否上所有的好友和关注者全部清空了。当然，如果没有程序的帮忙，估计还不等我删完我也就后悔了。 我没有那么狠心的把饭否的消息给清空，因为消息是不可恢复的（而且也太多了），但好友和关注者是可以的。做事情都给自己留后路显然是我一贯的风格，不然的话，我大概早从我家阳台跳下去了…… 两段脚本都不长，第一段是备份饭否的好友列表和关注者列表的，做的毫无泛用性，因为 bash 编程我并不很熟，只知道可以用 wget 来抓取。本来这种事情其实可以直接用 API 抓的，不过我想抓下我能直接看的东西，所以最终还是导出了 Cookie 抓网页。 第一段代码如下： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #!/bin/bash &#160; mkdir friends for i in &#123;1..11&#125; [...]]]></description>
			<content:encoded><![CDATA[<p>前几天因为某些原因，我把饭否上所有的好友和关注者全部清空了。当然，如果没有程序的帮忙，估计还不等我删完我也就后悔了。</p>
<p>我没有那么狠心的把饭否的消息给清空，因为消息是不可恢复的（而且也太多了），但好友和关注者是可以的。做事情都给自己留后路显然是我一贯的风格，不然的话，我大概早从我家阳台跳下去了……<br />
<span id="more-1197"></span><br />
两段脚本都不长，第一段是备份饭否的好友列表和关注者列表的，做的毫无泛用性，因为 bash 编程我并不很熟，只知道可以用 wget 来抓取。本来这种事情其实可以直接用 API 抓的，不过我想抓下我能直接看的东西，所以最终还是导出了 Cookie 抓网页。</p>
<p>第一段代码如下：</p>

<div class="wp_codebox"><table><tr id="p11973"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code" id="p1197code3"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> friends
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #000000;">1</span>..11<span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-k</span> <span style="color: #660033;">-e</span> <span style="color: #007800;">robots</span>=off <span style="color: #660033;">--load-cookies</span> cookies.txt <span style="color: #660033;">-P</span> friends<span style="color: #000000; font-weight: bold;">/</span> \
        http:<span style="color: #000000; font-weight: bold;">//</span>fanfou.com<span style="color: #000000; font-weight: bold;">/</span>friends<span style="color: #000000; font-weight: bold;">/</span>upsuper<span style="color: #000000; font-weight: bold;">/</span>p.<span style="color: #007800;">$i</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/friends\/upsuper\///g&quot;</span> \
        <span style="color: #ff0000;">&quot;friends/p.<span style="color: #007800;">$i</span>&quot;</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/friends/p.1/g&quot;</span> \
        <span style="color: #ff0000;">&quot;friends/p.<span style="color: #007800;">$i</span>&quot;</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/followers/..\/followers\/p.1/g&quot;</span> \
        <span style="color: #ff0000;">&quot;friends/p.<span style="color: #007800;">$i</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> followers
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #000000;">1</span>..8<span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-k</span> <span style="color: #660033;">-e</span> <span style="color: #007800;">robots</span>=off <span style="color: #660033;">--load-cookies</span> cookies.txt <span style="color: #660033;">-P</span> followers<span style="color: #000000; font-weight: bold;">/</span> \
        http:<span style="color: #000000; font-weight: bold;">//</span>fanfou.com<span style="color: #000000; font-weight: bold;">/</span>followers<span style="color: #000000; font-weight: bold;">/</span>upsuper<span style="color: #000000; font-weight: bold;">/</span>p.<span style="color: #007800;">$i</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/followers\/upsuper\///g&quot;</span> \
        <span style="color: #ff0000;">&quot;followers/p.<span style="color: #007800;">$i</span>&quot;</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/friends/..\/friends\/p.1/g&quot;</span> \
        <span style="color: #ff0000;">&quot;followers/p.<span style="color: #007800;">$i</span>&quot;</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/followers/p.1/g&quot;</span> \
        <span style="color: #ff0000;">&quot;followers/p.<span style="color: #007800;">$i</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">for</span> f <span style="color: #000000; font-weight: bold;">in</span> friends<span style="color: #000000; font-weight: bold;">/*</span> followers<span style="color: #000000; font-weight: bold;">/*</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/friends/..\/friends/g&quot;</span> \
        <span style="color: #ff0000;">&quot;followers/p.<span style="color: #007800;">$i</span>&quot;</span>
    <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/http:\/\/fanfou\.com\/followers/..\/followers/g&quot;</span> \
        <span style="color: #ff0000;">&quot;friends/p.<span style="color: #007800;">$i</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<p>想用的话，其中前两个 for 循环的数字必须改成自己的实际情况，里面的 upsuper 也要全数替换为自己的饭否ID，还有一个 cookies.txt 文件，可以用 Firefox 的 Cookie Exporter 插件从浏览器导出。</p>
<p>这个脚本非常值得赞美的一点是自动修复了所有的链接，使得在本地的页面全部可以通过链接进入，不在本地的页面也可以链接到饭否。这也是我调了很长世间的东西……</p>
<p>第二段脚本就是颇具破坏性的了：</p>

<div class="wp_codebox"><table><tr id="p11974"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="code" id="p1197code4"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: utf8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> json
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">socket</span> <span style="color: #ff7700;font-weight:bold;">import</span> timeout
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlencode
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">base64</span> <span style="color: #ff7700;font-weight:bold;">import</span> b64encode
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">getpass</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">getpass</span>
<span style="color: #ff7700;font-weight:bold;">from</span> httplib2 <span style="color: #ff7700;font-weight:bold;">import</span> Http
&nbsp;
username = <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Username: '</span><span style="color: black;">&#41;</span>
password = <span style="color: #dc143c;">getpass</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Password: '</span><span style="color: black;">&#41;</span>
auth = <span style="color: #483d8b;">'Basic '</span> + b64encode<span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s:%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>username, password<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
headers = <span style="color: black;">&#123;</span> <span style="color: #483d8b;">'Authorization'</span>: auth <span style="color: black;">&#125;</span>
&nbsp;
h = Http<span style="color: black;">&#40;</span>timeout=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span> = <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Delete friends</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Delete friends:'</span>
resp, content = h.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://api.fanfou.com/friends/ids.json'</span>, headers=headers<span style="color: black;">&#41;</span>
friends = json.<span style="color: black;">loads</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> friend <span style="color: #ff7700;font-weight:bold;">in</span> friends:
    query_str = urlencode<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span> <span style="color: #483d8b;">'id'</span>: friend.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> friend.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>,
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        resp, content = h.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://api.fanfou.com/friendships/destroy.json?'</span> + query_str, <span style="color: #483d8b;">'POST'</span>, headers=headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> timeout:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'timeout'</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> resp.<span style="color: black;">status</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Delete followers</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Delete followers:'</span>
resp, content = h.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://api.fanfou.com/followers/ids.json'</span>, headers=headers<span style="color: black;">&#41;</span>
followers = json.<span style="color: black;">loads</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> follower <span style="color: #ff7700;font-weight:bold;">in</span> followers:
    query_str = urlencode<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span> <span style="color: #483d8b;">'id'</span>: follower.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span> <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> follower.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>,
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        resp, content = h.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://api.fanfou.com/blocks/create.xml?'</span> + query_str, <span style="color: #483d8b;">'POST'</span>, headers=headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> timeout:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'timeout'</span>,
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> resp.<span style="color: black;">status</span>,
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        resp, content = h.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://api.fanfou.com/blocks/destroy.xml?'</span> + query_str, <span style="color: #483d8b;">'POST'</span>, headers=headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> timeout:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'timeout'</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> resp.<span style="color: black;">status</span></pre></td></tr></table></div>

<p>这段 Python 脚本其实颇具我写饭否应用的风格。这段脚本还是比较有泛用性的，进入的时候会提示输入饭否id和密码，然后他也会自动备份一个 JSON 格式的饭否好友列表和关注者列表。只是处于周全我才做的这一步，其实是完全没有必要的，因为我已经备份过了，而且我也不准备让程序帮我全部还原……</p>
<p>正好清理一下两个列表……</p>
<p>原理就不多做介绍了。第二段脚本在运行开始清理好友的时候，可能会连续出现 timeout 的情况不必在意，因为饭否似乎会在这个 API 执行的时候处理 timeline 的缓存。不过据我观察，脚本运行结束后，似乎会有部分好友留下，数量对我来说少于十个，可以快速手动清除……</p>
<p>出于观察输出的考虑，我没有用多线程。脚本删除关注者的原理是加入黑名单再取消黑名单，如果加入了黑名单在取消的时候没有成功，那就意味着误加了，这是找不到的，因为黑名单的列表似乎无法察看……</p>
<p>就这样了……我现在已经逐渐的开始恢复饭否活动了……不过还不准备完全回到过去……以上</p>
<p>突然觉得，第一段脚本可以用 make 实现？</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/two-scripts-for-fanfou/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rhythmbox 封面艺人插件的中国版</title>
		<link>http://blog.upsuper.org/china-mod-of-artdisplay-plugin-for-rhythmbox/</link>
		<comments>http://blog.upsuper.org/china-mod-of-artdisplay-plugin-for-rhythmbox/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 05:17:05 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[rhythmbox]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=1186</guid>
		<description><![CDATA[上一篇日志里面我做了一个从 VeryCD 为 Rhythmbox 提取专辑封面的程序，后来想到豆瓣其实也有这个东西，于是又做了一个豆瓣的。然后想，既然这样我干脆把原来的封面艺人插件 fork 出来，自己开一个新项目，专门做封面艺人插件的 China Mod~ 现在已经开好了，就在 Google Code 上：http://code.google.com/p/rhythmbox-artdisplay-cn/ 其实说 Mod 也不算，就是加了几个扩展进去……主要是考虑到如果不 fork 似乎很单独安装，所以就 fork 出来了……那个插件看过去也很长时间没有更新了呢？ 第一个版本0.1可以点击这里下载：rhythmbox-artdisplay-cn-0.1.tar.bz2，暂时还没有做任何安装包，deb 包和 arch 的包应该会随后奉上~ 安装很简单，常规的 make 和 make install 就可以了~ 如果各位有什么改进意见，欢迎提出~]]></description>
			<content:encoded><![CDATA[<p>上一篇日志里面我做了一个从 VeryCD 为 Rhythmbox 提取专辑封面的程序，后来想到豆瓣其实也有这个东西，于是又做了一个豆瓣的。然后想，既然这样我干脆把原来的封面艺人插件 fork 出来，自己开一个新项目，专门做封面艺人插件的 China Mod~</p>
<p>现在已经开好了，就在 Google Code 上：<a href="http://code.google.com/p/rhythmbox-artdisplay-cn/">http://code.google.com/p/rhythmbox-artdisplay-cn/</a></p>
<p>其实说 Mod 也不算，就是加了几个扩展进去……主要是考虑到如果不 fork 似乎很单独安装，所以就 fork 出来了……那个插件看过去也很长时间没有更新了呢？</p>
<p>第一个版本0.1可以点击这里下载：<a href="http://rhythmbox-artdisplay-cn.googlecode.com/files/rhythmbox-artdisplay-cn-0.1.tar.bz2">rhythmbox-artdisplay-cn-0.1.tar.bz2</a>，暂时还没有做任何安装包，deb 包和 arch 的包应该会随后奉上~</p>
<p>安装很简单，常规的 make 和 make install 就可以了~</p>
<p>如果各位有什么改进意见，欢迎提出~</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/china-mod-of-artdisplay-plugin-for-rhythmbox/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>寻找更高仿的 ID 第二季</title>
		<link>http://blog.upsuper.org/finding-higher-imitation-of-id-second-season/</link>
		<comments>http://blog.upsuper.org/finding-higher-imitation-of-id-second-season/#comments</comments>
		<pubDate>Sat, 11 Sep 2010 07:31:17 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[贴吧]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=1172</guid>
		<description><![CDATA[继上一篇文章之后，我又下大力气对这个程序做了许多修改，在精确度和速度方面似乎都有些许提高。在此推出第二季~ 使用真正的12px宋体 在上一次的程序中使用的 PIL 似乎是因为不支持宋体 ttc 文件中对于小字体下优化的点阵形式，才在选择小于 19px 的字号时不能正确渲染汉字。考虑到这一点，我就想到把 ttc 文件里面 12px 的点阵字体单独提取出来使用，毕竟贴吧上面显示 ID 都是用这个字号显示的。 使用 FontForge 提取出来了 simsun-12.bdf 文件，就是宋体 12px 下的点阵。参考 PIL 的手册，发现 PIL 不能直接使用 .bdf 文件，需要使用一个叫做 pilfont 的脚本转换成专有的 .pil 文件才行。我想转换就转换呗。simsun-12.bdf 一个 2.4MB 的文件，转换完就剩不到 100KB，我就觉得肯定有问题，用 PIL 导入，发现还是不能渲染中文。后来知道，这个 .pil 文件根本不支持非拉丁字母的字符，它的储存空间限定了 256 个字符…… 无奈了，这意味着 PIL 完全无法支持中文点阵了…… 当然，办法总归是有的，那就是——抛弃 PIL！为什么我能有这样的想法呢，因为看到 .bdf 文件是 UNIX 标准的。UNIX 标准意味着什么呢？记不记得 UNIX 有一个非常好的传统叫做，尽量使用纯文本。是的，这虽然让有些文件会变得太大，不过同时也让这些东西更容易被其他程序读取，而 .bdf [...]]]></description>
			<content:encoded><![CDATA[<p>继上一篇文章之后，我又下大力气对这个程序做了许多修改，在精确度和速度方面似乎都有些许提高。在此推出第二季~</p>
<h3>使用真正的12px宋体</h3>
<p>在上一次的程序中使用的 PIL 似乎是因为不支持宋体 ttc 文件中对于小字体下优化的点阵形式，才在选择小于 19px 的字号时不能正确渲染汉字。考虑到这一点，我就想到把 ttc 文件里面 12px 的点阵字体单独提取出来使用，毕竟贴吧上面显示 ID 都是用这个字号显示的。</p>
<p>使用 FontForge 提取出来了 simsun-12.bdf 文件，就是宋体 12px 下的点阵。参考 PIL 的手册，发现 PIL 不能直接使用 .bdf 文件，需要使用一个叫做 pilfont 的脚本转换成专有的 .pil 文件才行。我想转换就转换呗。simsun-12.bdf 一个 2.4MB 的文件，转换完就剩不到 100KB，我就觉得肯定有问题，用 PIL 导入，发现还是不能渲染中文。后来知道，这个 .pil 文件根本不支持非拉丁字母的字符，它的储存空间限定了 256 个字符……</p>
<p>无奈了，这意味着 PIL 完全无法支持中文点阵了……</p>
<p>当然，办法总归是有的，那就是——抛弃 PIL！为什么我能有这样的想法呢，因为看到 .bdf 文件是 UNIX 标准的。UNIX 标准意味着什么呢？记不记得 UNIX 有一个非常好的传统叫做，尽量使用纯文本。是的，这虽然让有些文件会变得太大，不过同时也让这些东西更容易被其他程序读取，而 .bdf 恰好即使这么一种文件。</p>
<p>这样读取 .bdf 点阵字体文件的程序自己写不就好了，什么额外的库都不需要……当然，纠错性极弱就是了~</p>

<div class="wp_codebox"><table><tr id="p11729"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
</pre></td><td class="code" id="p1172code9"><pre class="python" style="font-family:monospace;">line_count = <span style="color: #ff4500;">0</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">global</span> line_count
    line_count += <span style="color: #ff4500;">1</span>
    line = f.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> line<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'simsun-12.bdf'</span>, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
    chars = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    line = <span style="color: black;">&#91;</span><span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #808080; font-style: italic;"># 获得字符总数</span>
        <span style="color: #ff7700;font-weight:bold;">while</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">'CHARS'</span>:
            line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># 读取所有字符</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">assert</span> read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'STARTCHAR'</span>
            line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># 编码</span>
            <span style="color: #ff7700;font-weight:bold;">assert</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'ENCODING'</span>
            char = <span style="color: #008000;">unichr</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># 绘制参数</span>
            <span style="color: #ff7700;font-weight:bold;">assert</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'BBX'</span>
            width, height, x1, y1 = <span style="color: black;">&#91;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
            x0, y0 = <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span> + x1, <span style="color: #ff4500;">12</span> - y1 - height<span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># 准备绘制文字</span>
            base_image = <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
            <span style="color: #808080; font-style: italic;"># 读取并绘制文字</span>
            line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">assert</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'BITMAP'</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>y0, y0 + height<span style="color: black;">&#41;</span>:
                line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
                bits = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>line, <span style="color: #ff4500;">16</span><span style="color: black;">&#41;</span>
                bits <span style="color: #66cc66;">&gt;&gt;</span>= <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">4</span> - width
                <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>x0 + width - <span style="color: #ff4500;">1</span>, x0 - <span style="color: #ff4500;">1</span>, -<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
                    base_image<span style="color: black;">&#91;</span>y<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span>x<span style="color: black;">&#93;</span> = bits <span style="color: #66cc66;">&amp;</span> <span style="color: #ff4500;">1</span>
                    bits <span style="color: #66cc66;">&gt;&gt;</span>= <span style="color: #ff4500;">1</span>
            chars<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span> = base_image
            <span style="color: #808080; font-style: italic;"># 结束这个文字</span>
            line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">assert</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'ENDCHAR'</span>
        line = read_split<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">assert</span> line<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'ENDFONT'</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AssertionError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'line'</span>, line_count
        <span style="color: #ff7700;font-weight:bold;">raise</span></pre></td></tr></table></div>

<p>这样所有的字符就被读入，并变成一个单色像素二位数组了。</p>
<p>当然，这个性能很低，在我的机器上转换读取文件的2W+字符大概需要 18s，这可能也是为什么 PIL 要选择进行转换。事实上，使用纯文本储存一直以来都给 UNIX 风格的这一类软件带来一定性能缺陷。不过其实，这很值得，因为方便。</p>
<p>不过这个时间确实是太长了，更何况我们到目前为止还什么都没处理。怎么办呢？两个想法：一、优化代码；二、保存处理的数据。</p>
<p>第一种，基本上是没什么希望了，而且即使能优化，估计效果也不会太好，可能省个几秒封顶了。第二个显然不是个坏想法。</p>
<p>Python 在数据的持续化方面还是有很多现成的东西的，比如 pickle 什么的。不过那个速度太慢，而且是纯文本！好吧，偶尔我也会不喜欢纯文本，因为在这里意义不大……因此选择了 marshal。marshal 也是一个用于数据持续化的库，不过仅能对 Python 的内部类型进行。我会看中它最重要的原因就是它的应用范围极其有限，只能持续化内部类型。如果一个 Python 标准库，它有很明显的限制，却没有标明不推荐或在新版中被剔除，说明它必然有一个其他库不可及的优势。对于 marshal，我猜它的优势就是效率。</p>
<p>使用 marshal 就很简单了……</p>

<div class="wp_codebox"><table><tr id="p117210"><td class="line_numbers"><pre>62
63
</pre></td><td class="code" id="p1172code10"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">marshal</span>
<span style="color: #dc143c;">marshal</span>.<span style="color: black;">dump</span><span style="color: black;">&#40;</span>chars, <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'base_image'</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>这样后面的处理不需要不断重复这个低效的步骤了~</p>
<h3>处理文字图像</h3>
<p>原来是用 PIL 处理文字图像，现在抛弃 PIL 了，就得自己写了……不过这样也很好，自由发挥的空间很大了~</p>
<p>我猜用的是 Matrix67 大牛的那种在附近留阴影的方法，不过似乎我写的不够好就是了，怎么测试效果都不大理想。除此之外，纯 Python 实现的算法效率和 PIL 这种包装还是没得比，很简单的算法却慢的不得了……</p>
<p>下面是目前的处理代码：</p>

<div class="wp_codebox"><table><tr id="p117211"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code" id="p1172code11"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: utf8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">marshal</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">copy</span>
&nbsp;
base_chars = <span style="color: #dc143c;">marshal</span>.<span style="color: black;">load</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'base_image'</span>, <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
chars = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> char, image <span style="color: #ff7700;font-weight:bold;">in</span> base_chars.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    new_image = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span>:
        new_row = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> image<span style="color: black;">&#91;</span>y<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span>x<span style="color: black;">&#93;</span>:
                value = <span style="color: #ff4500;">81</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                value = <span style="color: #ff4500;">0</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> y <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> image<span style="color: black;">&#91;</span>y-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span>x<span style="color: black;">&#93;</span>:
                value += <span style="color: #ff4500;">4</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> y <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">13</span> <span style="color: #ff7700;font-weight:bold;">and</span> image<span style="color: black;">&#91;</span>y+<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span>x<span style="color: black;">&#93;</span>:
                value += <span style="color: #ff4500;">4</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> x <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> image<span style="color: black;">&#91;</span>y<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span>x-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>:
                value += <span style="color: #ff4500;">4</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> x <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">13</span> <span style="color: #ff7700;font-weight:bold;">and</span> image<span style="color: black;">&#91;</span>y<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span>x+<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>:
                value += <span style="color: #ff4500;">4</span>
            new_image.<span style="color: black;">append</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>
    chars<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span> = new_image
&nbsp;
<span style="color: #dc143c;">marshal</span>.<span style="color: black;">dump</span><span style="color: black;">&#40;</span>chars, <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'advanced_data'</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>处理效果不是很理想就是了，耗时大概也是 30s+。</p>
<h3>寻找相似字符</h3>
<p>其实这个部分就是一样的了……直接贴代码好了……</p>

<div class="wp_codebox"><table><tr id="p117212"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code" id="p1172code12"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: utf8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">marshal</span>
&nbsp;
chars = <span style="color: #dc143c;">marshal</span>.<span style="color: black;">load</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'advanced_data'</span>, <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> image_diff<span style="color: black;">&#40;</span>image1, image2<span style="color: black;">&#41;</span>:
    ret = <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> v1, v2 <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>image1, image2<span style="color: black;">&#41;</span>:
        ret += <span style="color: black;">&#40;</span>v1 - v2<span style="color: black;">&#41;</span> <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> ret
&nbsp;
remember_number = <span style="color: #ff4500;">5</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
    searched = <span style="color: #dc143c;">marshal</span>.<span style="color: black;">load</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'searched_chars'</span>, <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span>:
    searched = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
    input_string = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ID: '</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> input_string:
        <span style="color: #ff7700;font-weight:bold;">break</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> char <span style="color: #ff7700;font-weight:bold;">in</span> input_string:
        <span style="color: #ff7700;font-weight:bold;">if</span> char <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> chars:
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> char <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> searched:
            diff_data = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
            image = chars<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> c, v <span style="color: #ff7700;font-weight:bold;">in</span> chars.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> c == char:
                    <span style="color: #ff7700;font-weight:bold;">continue</span>
                diff_data.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>image_diff<span style="color: black;">&#40;</span>v, image<span style="color: black;">&#41;</span>, c<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            diff_data.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            searched<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span> = diff_data<span style="color: black;">&#91;</span>:remember_number<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> char,
        <span style="color: #ff7700;font-weight:bold;">for</span> item <span style="color: #ff7700;font-weight:bold;">in</span> searched<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> u<span style="color: #483d8b;">'({0}, {1})'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>item<span style="color: black;">&#41;</span>,
        <span style="color: #ff7700;font-weight:bold;">print</span>
    <span style="color: #ff7700;font-weight:bold;">print</span>
&nbsp;
<span style="color: #dc143c;">marshal</span>.<span style="color: black;">dump</span><span style="color: black;">&#40;</span>searched, <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'searched_chars'</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>和上次不同的是查找过的字会被保存下来，效率可以高一些……</p>
<h3>继续改进</h3>
<p>现在的主要问题就是如何提高相似度的识别精度了……目前的想法是通过逐像素比对测试两个字的相似度，最多加一些模糊化什么的处理。doggy 提出一个想法是计算连通区域面积的比例，我个人认为不大可行……我的想法是识别文字的笔画，把文字的骨架弄出来，然后对比什么的，可能效果更好吧？</p>
<p>不知道各位还有没有其他什么想法？</p>
<h3>下载</h3>
<p>最后是完整版的目前的程序以及已经生成的数据，各位有兴趣可以直接拿来试用了……<a href="http://down.upsuper.org/find-similar-character.tar.bz2">find-similar-character.tar.bz2</a> (1.7MB)</p>
<h3>参考资料</h3>
<ul>
<li><a href="http://www.pkucn.com/viewthread.php?tid=202692">我想把simsun.ttf里的12号点阵字体单独提取出来做成一个ttf &#8211; 北大中文论坛</a></li>
<li><a href="http://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format">Glyph Bitmap Distribution Format &#8211; Wikipedia</a></li>
<li><a href="http://www.adobe.com/devnet/font/pdfs/5005.BDF_Spec.pdf">Glyph Bitmap Distribution Format (BDF) Specification &#8211; Adobe Developer Support</a></li>
<li><a href="http://docs.python.org/library/marshal.html">marshal — Internal Python object serialization &#8211; Python documentation</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/finding-higher-imitation-of-id-second-season/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>寻找更高仿的 ID</title>
		<link>http://blog.upsuper.org/finding-higher-imitation-of-id/</link>
		<comments>http://blog.upsuper.org/finding-higher-imitation-of-id/#comments</comments>
		<pubDate>Thu, 09 Sep 2010 10:21:43 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[贴吧]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=1169</guid>
		<description><![CDATA[今天大学军训完了，不想做什么正经事，就想到前一段时间想做的寻找相似汉字的程序，用以寻找更高仿的贴吧 ID。用程序来寻找相似汉字，从另一个角度，也是从 Matrix67 大牛的一篇日志里得到的启发。不过 Matrix67 大牛使用的是 Mathematica 来寻找，我不大会 Mathematica，就想用我熟悉的 Python 来解决，毕竟 Python 是一个很强大的东西~ 其实寻找的思路很简单，就是把某个汉字当作图片弄出来，让后对比两个图片的相似程度。因此做这个程序的第一步就是研究如何用 Python 处理图片和文字。Python 有一个非常著名的第三方库，名叫 Python Imaging Library，简称 PIL，就是专门用来处理图片的。 文字 to 图像 PIL 可以很轻松的将文字转换为图像，并且提供了虽然不能说是强大，但暂时够用的图像处理函数。 处理文字生成的图像，显然和彩色没有太大关系，因此可以使用灰度图像节省计算需要的空间和时间。此外我们知道，文字到图像有一个中间媒介，就是字体。因此我们必须先确定我们需要的字体和大小。用 Firebug 考查贴吧用于显示 ID 的字体和大小，发现是宋体 12px。这样参考 PIL 的手册，就有了最基本的文字到图片的代码了： 1 2 3 4 5 6 import Image, ImageDraw, ImageFont image = Image.new&#40;'L', &#91;14, 14&#93;, 255&#41; draw = ImageDraw.Draw&#40;image&#41; font = [...]]]></description>
			<content:encoded><![CDATA[<p>今天大学军训完了，不想做什么正经事，就想到前一段时间想做的寻找相似汉字的程序，用以寻找更高仿的贴吧 ID。用程序来寻找相似汉字，从另一个角度，也是从 Matrix67 大牛的一篇日志里得到的启发。不过 Matrix67 大牛使用的是 Mathematica 来寻找，我不大会 Mathematica，就想用我熟悉的 Python 来解决，毕竟 Python 是一个很强大的东西~<br />
<span id="more-1169"></span><br />
其实寻找的思路很简单，就是把某个汉字当作图片弄出来，让后对比两个图片的相似程度。因此做这个程序的第一步就是研究如何用 Python 处理图片和文字。Python 有一个非常著名的第三方库，名叫 Python Imaging Library，简称 PIL，就是专门用来处理图片的。</p>
<h3>文字 to 图像</h3>
<p>PIL 可以很轻松的将文字转换为图像，并且提供了虽然不能说是强大，但暂时够用的图像处理函数。</p>
<p>处理文字生成的图像，显然和彩色没有太大关系，因此可以使用灰度图像节省计算需要的空间和时间。此外我们知道，文字到图像有一个中间媒介，就是字体。因此我们必须先确定我们需要的字体和大小。用 Firebug 考查贴吧用于显示 ID 的字体和大小，发现是宋体 12px。这样参考 PIL 的手册，就有了最基本的文字到图片的代码了：</p>

<div class="wp_codebox"><table><tr id="p116918"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p1169code18"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> Image, ImageDraw, ImageFont
image = Image.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">14</span>, <span style="color: #ff4500;">14</span><span style="color: black;">&#93;</span>, <span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span>
draw = ImageDraw.<span style="color: black;">Draw</span><span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>
font = ImageFont.<span style="color: black;">truetype</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'simsun.ttc'</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
draw.<span style="color: black;">text</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, u<span style="color: #483d8b;">'好'</span>, font=font<span style="color: black;">&#41;</span>
image.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'hw.png'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>看过去这个代码是正确的，不过在查看 hw.png 后，我发现并没有出现预期的“好”字，而是一堆混乱的东西，不知何故。后经过不断实验，发现只有当初始的文字大小设定为19或以上时，文字才可以被正确地绘制出来，_-b</p>
<p>于是不得不修改这段代码，让它先绘制一个大的，再缩放成需要的大小：</p>

<div class="wp_codebox"><table><tr id="p116919"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p1169code19"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> Image, ImageDraw, ImageFont
image = Image.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">28</span>, <span style="color: #ff4500;">28</span><span style="color: black;">&#93;</span>, <span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span>
draw = ImageDraw.<span style="color: black;">Draw</span><span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>
font = ImageFont.<span style="color: black;">truetype</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'simsun.ttc'</span>, <span style="color: #ff4500;">24</span><span style="color: black;">&#41;</span>
draw.<span style="color: black;">text</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>, u<span style="color: #483d8b;">'好'</span>, font=font<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># 抗锯齿方式缩放</span>
image = image.<span style="color: black;">resize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span>, <span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span>, Image.<span style="color: black;">ANTIALIAS</span><span style="color: black;">&#41;</span>
image.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'hw.png'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>效果还不错。</p>
<h3>枚举汉字</h3>
<p>然后来找一种方式来枚举汉字。参考维基百科的 GB2312 条目，确定了 GB2312 中汉字区的编码，为第一个字节 0xB0-0xF7，第二个字节 0xA1-0xFE，其中 D7FA-D7FE 是空的，这样共有6763个汉字拿来搞。</p>
<p>其实还是挺少的就是了……</p>
<p>于是枚举汉字的代码：</p>

<div class="wp_codebox"><table><tr id="p116920"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p1169code20"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>0xB0, 0xF8<span style="color: black;">&#41;</span>:
    chr_i = <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> j <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>0xA1, 0xFF<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> i == 0xD7 <span style="color: #ff7700;font-weight:bold;">and</span> j <span style="color: #66cc66;">&gt;</span>= 0xFA <span style="color: #ff7700;font-weight:bold;">and</span> j <span style="color: #66cc66;">&lt;</span>= 0xFE:
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        char = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>chr_i + <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>j<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'gb18030'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> char,</pre></td></tr></table></div>

<h3>初步成果</h3>
<p>现在结合上面两段，得到了下面的初步代码：</p>

<div class="wp_codebox"><table><tr id="p116921"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="code" id="p1169code21"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: UTF-8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> Image, ImageDraw, ImageFont, ImageFilter
&nbsp;
font = ImageFont.<span style="color: black;">truetype</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'simsun.ttc'</span>, <span style="color: #ff4500;">24</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_char_data<span style="color: black;">&#40;</span>char<span style="color: black;">&#41;</span>:
    image = Image.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">28</span>, <span style="color: #ff4500;">28</span><span style="color: black;">&#93;</span>, <span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span>
    draw = ImageDraw.<span style="color: black;">Draw</span><span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>
    draw.<span style="color: black;">text</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>, char, font=font<span style="color: black;">&#41;</span>
    image = image.<span style="color: black;">resize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span>, <span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span>, Image.<span style="color: black;">ANTIALIAS</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>image.<span style="color: black;">getdata</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> diff_of_data<span style="color: black;">&#40;</span>data1, data2<span style="color: black;">&#41;</span>:
    ret = <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>data1, data2<span style="color: black;">&#41;</span>:
        ret += <span style="color: #008000;">abs</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> - i<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> ret
&nbsp;
chars = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>0xB0, 0xF8<span style="color: black;">&#41;</span>:
    chr_i = <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> j <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>0xA1, 0xFF<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> i == 0xD7 <span style="color: #ff7700;font-weight:bold;">and</span> j <span style="color: #66cc66;">&gt;</span>= 0xFA <span style="color: #ff7700;font-weight:bold;">and</span> j <span style="color: #66cc66;">&lt;</span>= 0xFE:
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        char = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>chr_i + <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>j<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'gb18030'</span><span style="color: black;">&#41;</span>
        chars<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span> = get_char_data<span style="color: black;">&#40;</span>char<span style="color: black;">&#41;</span>
&nbsp;
remember_number = <span style="color: #ff4500;">5</span>
input_string = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ID: '</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> input_char <span style="color: #ff7700;font-weight:bold;">in</span> input_string:
    <span style="color: #ff7700;font-weight:bold;">if</span> input_char <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> chars:
        <span style="color: #ff7700;font-weight:bold;">print</span> input_char
        <span style="color: #ff7700;font-weight:bold;">continue</span>
    input_data = chars<span style="color: black;">&#91;</span>input_char<span style="color: black;">&#93;</span>
    diff_list = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> char, data <span style="color: #ff7700;font-weight:bold;">in</span> chars.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> char == input_char:
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        diff_list.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>diff_of_data<span style="color: black;">&#40;</span>data, input_data<span style="color: black;">&#41;</span>, char<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    diff_list.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> input_char,
    <span style="color: #ff7700;font-weight:bold;">for</span> diff, char <span style="color: #ff7700;font-weight:bold;">in</span> diff_list<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> u<span style="color: #483d8b;">'({0}, {1})'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>diff, char<span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>.<span style="color: black;">ljust</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">11</span><span style="color: black;">&#41;</span>,
    <span style="color: #ff7700;font-weight:bold;">print</span></pre></td></tr></table></div>

<p>发现效果还有待提高，并且每次测试一个新 ID 都要做一次预处理，每次预处理大概需要6s左右。</p>
<h3>目前代码</h3>
<p>对上面的代码做了一些修改，包括对文字图像做一些处理，以使其查找出的相似文字能更接近人的感觉，并且让一次预处理可以做多次比对，得到了下面代码：</p>

<div class="wp_codebox"><table><tr id="p116922"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="code" id="p1169code22"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: UTF-8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> Image, ImageDraw, ImageFont, ImageFilter
&nbsp;
font = ImageFont.<span style="color: black;">truetype</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'simsun.ttc'</span>, <span style="color: #ff4500;">24</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_char_data<span style="color: black;">&#40;</span>char<span style="color: black;">&#41;</span>:
    image = Image.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">28</span>, <span style="color: #ff4500;">28</span><span style="color: black;">&#93;</span>, <span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span>
    draw = ImageDraw.<span style="color: black;">Draw</span><span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>
    draw.<span style="color: black;">text</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>, char, font=font<span style="color: black;">&#41;</span>
    image = image.<span style="color: black;">resize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">14</span>, <span style="color: #ff4500;">14</span><span style="color: black;">&#41;</span>, Image.<span style="color: black;">ANTIALIAS</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># XXX 期待更好的处理方式</span>
    image = image.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>ImageFilter.<span style="color: black;">SHARPEN</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>ImageFilter.<span style="color: black;">SMOOTH</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>image.<span style="color: black;">getdata</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> diff_of_data<span style="color: black;">&#40;</span>data1, data2<span style="color: black;">&#41;</span>:
    ret = <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>data1, data2<span style="color: black;">&#41;</span>:
        ret += <span style="color: #008000;">abs</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> - i<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> ret
&nbsp;
chars = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>0xB0, 0xF8<span style="color: black;">&#41;</span>:
    chr_i = <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> j <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>0xA1, 0xFF<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> i == 0xD7 <span style="color: #ff7700;font-weight:bold;">and</span> j <span style="color: #66cc66;">&gt;</span>= 0xFA <span style="color: #ff7700;font-weight:bold;">and</span> j <span style="color: #66cc66;">&lt;</span>= 0xFE:
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        char = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>chr_i + <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>j<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'gb18030'</span><span style="color: black;">&#41;</span>
        chars<span style="color: black;">&#91;</span>char<span style="color: black;">&#93;</span> = get_char_data<span style="color: black;">&#40;</span>char<span style="color: black;">&#41;</span>
&nbsp;
remember_number = <span style="color: #ff4500;">5</span>
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
    input_string = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ID: '</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> input_string:
        <span style="color: #ff7700;font-weight:bold;">break</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> input_char <span style="color: #ff7700;font-weight:bold;">in</span> input_string:
        <span style="color: #ff7700;font-weight:bold;">if</span> input_char <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> chars:
            <span style="color: #ff7700;font-weight:bold;">print</span> input_char
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        input_data = chars<span style="color: black;">&#91;</span>input_char<span style="color: black;">&#93;</span>
        diff_list = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> char, data <span style="color: #ff7700;font-weight:bold;">in</span> chars.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> char == input_char:
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            diff_list.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>diff_of_data<span style="color: black;">&#40;</span>data, input_data<span style="color: black;">&#41;</span>, char<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        diff_list.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> input_char,
        <span style="color: #ff7700;font-weight:bold;">for</span> diff, char <span style="color: #ff7700;font-weight:bold;">in</span> diff_list<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> u<span style="color: #483d8b;">'({0}, {1})'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>diff, char<span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>.<span style="color: black;">ljust</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">11</span><span style="color: black;">&#41;</span>,
        <span style="color: #ff7700;font-weight:bold;">print</span>
    <span style="color: #ff7700;font-weight:bold;">print</span></pre></td></tr></table></div>

<h3>继续改进</h3>
<p>目前这个程序测试的效果还行，不过还有待进一步改进。可改进的地方包括上面标出 XXX 的部分，即对文字图像进行处理的部分，或许可以有更好的处理方式。除此之外，如果能直接绘制出 12px 的字，必然也会有更好的效果。如果增大字库，从 GB2312 增加到 GB18030 的字库，可以用来对比的文字也会更多，也就更可能找到相似的字了~</p>
<p>这个，还有继续改进的余地嗯~有时间就继续努力咯……</p>
<h3>参考资料</h3>
<ul>
<li><a href="http://www.matrix67.com/blog/archives/2907">用Mathematica寻找最相似的汉字 &#8211; Matrix67</a></li>
<li><a href="http://www.pythonware.com/library/pil/handbook/image.htm">The Image Module &#8211; Python Imaging Library Handbook</a></li>
<li><a href="http://www.pythonware.com/library/pil/handbook/imagefont.htm">The ImageFont Module &#8211; Python Imaging Library Handbook</a></li>
<li><a href="http://www.pythonware.com/library/pil/handbook/imagedraw.htm">The ImageDraw Module &#8211; Python Imaging Library Handbook</a></li>
<li><a href="http://www.pythonware.com/library/pil/handbook/imagefilter.htm">The ImageFilter Module &#8211; Python Imaging Library Handbook</a></li>
<li><a href="http://zh.wikipedia.org/zh-cn/GB_2312">GB 2312 &#8211; 维基百科</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/finding-higher-imitation-of-id/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>对比一下 Python 和 Erlang</title>
		<link>http://blog.upsuper.org/comparsion-between-python-and-erlang/</link>
		<comments>http://blog.upsuper.org/comparsion-between-python-and-erlang/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 11:10:39 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[探究学习]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=1134</guid>
		<description><![CDATA[今天突然有兴致来对比一下我在过去的一年中主要学习的两种语言，Python 和 Erlang，他们都是很神奇的语言。不过，在我看来，更神奇的是，这两种语言几乎是完全对立的！ 下面我弄了张表格来对比他们： 名称 Python Erlang 主要范型 面向对象 函数式、面向并发 开发者 Python 基金会 商业公司 爱立信 文件编码 在 Python 2 中默认为 ASCII，Python 3 中默认为 UTF-8，但都可以制定任意编码。 默认为 Latin-1，不允许指定文件编码。不过事实上编译器并不会在意文件中是否存在“不正确”的字符。 变量 几乎什么都是变量，变量都可以不断变化，无论是值还是类型。甚至你可以改变 True 和 False，让他们颠倒。（当然，也有例外，如 None，我至今没找到改变他的方法） 且不说原子是显然不可变的，任何一个变量被赋值之后，他的值也是不可变的，这是所谓变量绑定。（单次赋值） 字符串 拥有完善的字符串支持，在 Python 3 中这更是发挥到了极致。 根本不存在字符串类型，一切字符串都是字符列表，因此就更没有什么强大的字符串处理函数了。 列表 可以根据下标索引快速获取列表任意位置的内容。 考虑效率的话，只能从列表的头部摘取内容。 模块 依据文件系统的文件分布构建层级式的模块体系，使用模块前必须声明将模块引入当前名字空间。 所有模块是平行的，在同一层中，模块名称强制与文件名相同。使用模块时模块必须已经被编译，Erlang 将会自动寻找模块并读取。 并行 通过 GIL 这一全局锁将所有多线程操作退化为单线程操作，不存在任何并发性。（不过 Python 正在尝试加入新的模块来改变这一问题） 天生就是面向并发的……用他仅做顺序编程是一种莫大的浪费…… C 接口 [...]]]></description>
			<content:encoded><![CDATA[<p>今天突然有兴致来对比一下我在过去的一年中主要学习的两种语言，Python 和 Erlang，他们都是很神奇的语言。不过，在我看来，更神奇的是，这两种语言几乎是完全对立的！</p>
<p>下面我弄了张表格来对比他们：</p>
<table>
<tr>
<th width="20%">名称</th>
<th width="40%">Python</th>
<th width="40%">Erlang</th>
</tr>
<tr>
<th>主要范型</th>
<td>面向对象</td>
<td>函数式、面向并发</td>
</tr>
<tr>
<th>开发者</th>
<td>Python 基金会</td>
<td>商业公司 爱立信</td>
</tr>
<tr>
<th>文件编码</th>
<td>在 Python 2 中默认为 ASCII，Python 3 中默认为 UTF-8，但都可以制定任意编码。</td>
<td>默认为 Latin-1，不允许指定文件编码。不过事实上编译器并不会在意文件中是否存在“不正确”的字符。</td>
</tr>
<tr>
<th>变量</th>
<td>几乎什么都是变量，变量都可以不断变化，无论是值还是类型。甚至你可以改变 True 和 False，让他们颠倒。（当然，也有例外，如 None，我至今没找到改变他的方法）</td>
<td>且不说原子是显然不可变的，任何一个变量被赋值之后，他的值也是不可变的，这是所谓变量绑定。（单次赋值）</td>
</tr>
<tr>
<th>字符串</th>
<td>拥有完善的字符串支持，在 Python 3 中这更是发挥到了极致。</td>
<td>根本不存在字符串类型，一切字符串都是字符列表，因此就更没有什么强大的字符串处理函数了。</td>
</th>
<tr>
<th>列表</th>
<td>可以根据下标索引快速获取列表任意位置的内容。</td>
<td>考虑效率的话，只能从列表的头部摘取内容。</td>
</tr>
<tr>
<th>模块</th>
<td>依据文件系统的文件分布构建层级式的模块体系，使用模块前必须声明将模块引入当前名字空间。</td>
<td>所有模块是平行的，在同一层中，模块名称强制与文件名相同。使用模块时模块必须已经被编译，Erlang 将会自动寻找模块并读取。</td>
</tr>
<tr>
<th>并行</th>
<td>通过 GIL 这一全局锁将所有多线程操作退化为单线程操作，不存在任何并发性。（不过 Python 正在尝试加入新的模块来改变这一问题）</td>
<td>天生就是面向并发的……用他仅做顺序编程是一种莫大的浪费……</td>
</tr>
<tr>
<th>C 接口</th>
<td>使用 Python.h 编写接口，编译为动态链接库，运行时调入 Python 内使用。</td>
<td>编写外部程序，通过标准输入输出与 Erlang 主进程交换数据，在 Erlang 进程空间外单独运行。（也有一种在进程空间内运行的接口，不过不推荐使用）</td>
<tr>
<th>函数重载</th>
<td>不支持任何形式的函数重载，但支持可选参数。</td>
<td>支持参数数量不同的同名函数，但不支持可选参数。而且基于模式匹配，支持同一函数的不同分支的定义。</td>
</tr>
<tr>
<th>数据库</th>
<td>内置了通用的 SQLite 数据库支持，可以通过 SQL 语句进行数据库操作，储存的信息限制在文本、数字等几种。</td>
<td>内置了专用的 Mnesia，可以与 Erlang 无缝衔接地储存任何内容，通过 Erlang 的 qlc 模块不使用 SQL 语句进行数据库操作。（NoSQL）</td>
</tr>
<tr>
<th>代码热替换</th>
<td>支持使用 reload 函数重新载入一个模块。</td>
<td>模块的新版本被编译后任何调用即采用新的代码。</td>
</tr>
</table>
<p>可以看到这两种语言真的是非常非常不同，我想这和他们的设计初衷和适用范围是很有关系的：Python 大多数时候被用于快速的原型开发、用作胶水语言、创建小型桌面级应用程序；而 Erlang 则在一开始就被用在电信，这一对容错、并发要求较苛刻的领域。</p>
<p>不过我还是觉得，这两种语言都是非常优美的，以他们自己的专长而言。不过 Python 已经非常不错了，Erlang 在我看来则还有很大的发展空间~</p>
<p><em>PS：以上仅仅是就我自己的了解给出的一些对比，疏漏和错误在所难免，也希望看到了及时告诉我~</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/comparsion-between-python-and-erlang/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>支持 Haiti 的小网站</title>
		<link>http://blog.upsuper.org/a-small-site-for-haiti/</link>
		<comments>http://blog.upsuper.org/a-small-site-for-haiti/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 13:03:24 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[探究学习]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[公益]]></category>
		<category><![CDATA[兼容性]]></category>
		<category><![CDATA[地震]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=987</guid>
		<description><![CDATA[17号的时候虫子向我求助，想要我帮忙做一个支持海地的小网站。大体的思路就是，在上面的放一个大地图，然后大家可以留言、上传照片什么的，然后就在地图上出现亮点，然后亮点点进去可以看到留言和照片~这个网站已经进入公测了，大家可以在这里查看：Haiti]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.upsuper.org/wp-content/uploads/2010/01/Haiti-3_1264924757767.png"><img src="http://blog.upsuper.org/wp-content/uploads/2010/01/Haiti-3_1264924757767-300x211.png" alt="" title="Haiti &lt;3_1264924757767" width="300" height="211" class="alignright size-medium wp-image-1000" /></a>17号的时候虫子向我求助，想要我帮忙做一个支持海地的小网站。大体的思路就是，在上面的放一个大地图，然后大家可以留言、上传照片什么的，然后就在地图上出现亮点，然后亮点点进去可以看到留言和照片~这个网站已经进入公测了，大家可以在这里查看：<a href="http://haiti.dnand.org/">Haiti <3</a>（话说我曾经问虫子“<3”是什么意思，她告诉我，是爱心的意思~）</p>
<p>我猜从来没做过网站的人一定会觉得这个很简单，但我觉得一点都不简单……不过似乎可以实现~这种无疑又是对我技术的一次挑战！<br />
<span id="more-987"></span><br />
一开始，我想用一种十分取巧的方式——直接用 Google Maps~探究了一段时间的 Google Maps。结果虫子要求：一是地图要暗，二是要出来的是亮点。想想，Google Maps 还是算了呃……（话说其实也不是不可以，不过实现了，很多数据从客户端走，也不大好）。不过像 Google Maps 这样极好的地图图片来源实在是太难得了！于是就直接用了~</p>
<p>首先要攻克的第一个问题是，如果我们知道来访者的经纬度，如何知道把他的点点在地图的什么位置？这是一个很神奇的问题，想想经纬度是为球面设计的，现在要把它转换到一个平面上。说来也巧，原来参与过天文软件 Stellarium 某个版本的翻译工作，正好翻译了其中被称作地图投影的部分。因为有好几个不同的投影方式，我渐渐就明白了，那个就是把球面图形映射到平面的方法！于是就找到了地图投影，经过查询，发现 Google Maps 使用的是 <a href="http://en.wikipedia.org/wiki/Mercator_projection">Mercator projection</a> (<a href="http://zh.wikipedia.org/zh-cn/%E9%BA%A5%E5%8D%A1%E6%89%98%E6%8A%95%E5%BD%B1%E6%B3%95">麦卡托投影法/墨卡托投影法/正轴等角圆柱投影</a>)。找到了投影法的名称，自然转换公式不是难事~不过这个公式看不懂……呃……算了，那些公式显然不在我现在的数学水平能够理解的范围之内，直接用好了……</p>
<p>用前面探究到的 Google Maps 的东西，写了个网页，对比了一下 Google Maps 转换的坐标和我的程序转换的坐标之间的情况，发现基本相等，有一部分会出现 1px 的差异，我就直接忽略之了~在调试这个程序的过程中，比较重要的大概就是 PHP 里面的三角函数相关的函数使用的都是弧度，而我们习惯上使用的经纬度都是角度，这样就需要一点点的转换了……好在 PHP 提供了 deg2rad 这样方便的函数~话说我的地图投影这个程序我把它单独分了一个文件出来，主要是里面定义了各种地图转换需要的常数，如果和别的功能合在一起大约看过去会比较乱……</p>
<p>下面遇到第二个重大的问题是：我们如何知道来访者所在的经纬度？！这个问题似乎比上面那个更复杂了……当然你可以直接请来访者告诉你，不过更好的方法显然是根据 IP 地址识别一下。不过说到 IP 地址的识别精度，那我也无奈了。我猜想在 IPv6 普及前，想要准确根据 IP 地址识别出位置大约是不可能的了。不过，可以接受的精度还是可以实现的~国内的 IP 数据库如纯真这样的，提供的都是一个字符串地址，那个是只能给人看的，电脑可不知道那些东西表示什么……于是就转向了国外的 IP 数据库。果然找到了些有趣的数据库，里面能包含 IP 可能对应的经度和纬度，而且还提供 CSV 下载，可好了~这里可以找到这个好东西：<a href="http://ipinfodb.com/ip_database.php">IP address geolocation SQL database :: IPInfoDB</a>。然后我需要一个可以提供 PHP 快速查找的文件。其实这个事情第一次做音乐投票系统的时候，为了限制投票 IP 在福建境内，就做过这个东西。思路也很简单：把每个 IP 段的数据变成定长的二进制数据，然后需要的时候二分查找~于是有了下面的转换用 Python 脚本：</p>

<div class="wp_codebox"><table><tr id="p98724"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code" id="p987code24"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: UTF-8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">csv</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">struct</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
fin = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ip_group_city.csv'</span>, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
c = <span style="color: #dc143c;">csv</span>.<span style="color: black;">reader</span><span style="color: black;">&#40;</span>fin, delimiter=<span style="color: #483d8b;">';'</span>, quotechar=<span style="color: #483d8b;">'&quot;'</span><span style="color: black;">&#41;</span>
fout = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ipdata.dat'</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
a = <span style="color: #ff4500;">0</span>
s = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> r <span style="color: #ff7700;font-weight:bold;">in</span> c:
  a += <span style="color: #ff4500;">1</span>
  s.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">struct</span>.<span style="color: black;">pack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&gt;Iff2sh'</span>,
      <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
      <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
      r<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">float</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #483d8b;">'0'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> a <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">10000</span> == <span style="color: #ff4500;">0</span>:
    fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    s = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, a,
fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, a
fin.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
fout.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>这样，就当获取经纬度差不多了吧~嗯~虽然那个精度实在不敢恭维……不过根据那个网站自己的数据，至少国家是不会弄错的（准确度 90%+），只是城市就不跟你保证了~（那个数据貌似显示，这个数据库中城市在中国只有 71% 左右是正确的……）。</p>
<p>最后是关于地图的最后一个问题……如何绘制？</p>
<p>经过考察，这个小网站未来要放的那个服务器是不支持 ImageMagick 的，于是只能用 GD 库了……</p>
<p>那个小点点，其实就是圆咯。于是我一开始用 imageFilledEllipse 函数在地图上画直径为 3px 的圆。不过那个的效果实在是不大行……另外一件事就是关于上传照片的问题，某些相机比较囧的都把照片方向弄在 Exif 里面……虽然 PHP 有很方便的库可以直接读取 Exif，但旋转和翻转就麻烦了……</p>
<p>关于 GD 库，有一件事我觉得很无语，那就是有好几个比较有趣的函数，如 imageAntiAlias、imageRotate 下面都写着：<br />
<blockquote>
    <strong>Note:</strong> This function is only available if PHP is compiled with the bundled version of the GD library.
</p></blockquote>
<p>于是就各种囧的不能在我自己机子上调试……目标服务器的 GD 库倒是符合条件，不过我发现其实想要通用还有一种很好的方法：在 Notes 里面找！通常不能通用的函数在 Notes 里面都有相应的通用解决方案~这次我在 Notes 里面找到了图片翻转、旋转、判断 Exif 方向、平滑绘制圆的函数~我觉得有些时候，下面的 Notes 比上面的文档要有意义的多……平滑绘制圆的函数，我为了半透明又改了一点。当然，改的不完美，也就不敢拿出来献丑了，勉强能用就是了~</p>
<p>此外，还抄来了 WordPress 里面一段创建不同大小图片和创建缩略图的代码，很好用嗯~话说，太久没写 PHP，很多东西都忘的差不多了，比如说输入的数据中有单引号会自动被 PHP escape 掉，这还让我苦恼了一下呃……</p>
<p>另外就是，设计中虫子给我提出了一个神奇的要求：跟 twitter。为了这件事，我进行了各种不和谐的活动，以了解 twitter 的 APIs……然后用了一个带缓冲的转接程序弄好了。</p>
<p>至于客户端部分，我再次使用了 jQuery，jQuery 果然是个好东西。而且为了上传，我又使用了 Uploadify。有赖于<a href="http://blog.upsuper.org/2009-recommend-platform-of-music-recruiter-for-fuzhou-no1-middle-school/">上一次做音乐征集系统</a>的经验，这次少走了不少弯路，而且大量的 IE6 的 bug 也被我巧妙地解决了~而且我发现 IE6 的某些莫名其妙的 bug （比如我在制作过程中遇到了一个 div 明明 right 是 0，却超出右边界很多）都可以通过设置 zoom: 1; 来解决……不知道 IE6 这种莫名其妙的浏览器到底是什么样 SB 的团队制作出来的。IE 曾经是带领万维网发展的，现在却成为了严重的阻碍者！用 IE 的孩子们赶快觉醒吧……我真得不想在为了 IE 花掉大把的时间调试了……</p>
<p>顺便说一下新发现的 IE6 的 bug（其实我也不知道是不是我新发现的……）：还是隐藏显示的问题。是用 AlphaImageLoader 这个 filter 的元素隐藏后显示，这个 filter 的效果会消失，也就是没用了……为了这个 bug，这次不得不在脚本中都加入了 ie-fix……而且，更严重的是，如果你在显示后再设置这个 filter，又会出现另外一个 bug：这个时候，被设置这个 filter 的元素内部的所有元素可见，但变成不可用，也就是好像点不到一样！我估计是这个 filter 变成了一个在元素内部最上层的一个东西，于是就挡住了其他所有的元素。我汗啊，IE6 的 QA 是干什么吃的啊……这个的解决办法说来也简单，另外弄一个 div，设置在同样的位置，同样的长宽，对他用那个 filter 就行了……</p>
<p>对了对了！说到 AlphaImageLoader 这个 filter，我又想起来一件事，证明了百度不适合用来搜索技术资料，至少比 Google 逊太多了：你分别在这两个搜索引擎里面输入“filter:progid:DXImageTransform.Microsoft.AlphaImageLoader”，我把结果贴出来：</p>
<div style="width: 100%; text-align: center;"><a href="http://blog.upsuper.org/wp-content/uploads/2010/01/_filterprogidDXImageTransform.Microsoft.AlphaImageLoader_1264941140183-e1264941753180.png"><img src="http://blog.upsuper.org/wp-content/uploads/2010/01/_filterprogidDXImageTransform.Microsoft.AlphaImageLoader_1264941140183-e1264941753180-190x300.png" alt="" title="百度搜索_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader_1264941140183" width="190" height="300" class="alignnone size-medium wp-image-998" /></a><a href="http://blog.upsuper.org/wp-content/uploads/2010/01/filterprogidDXImageTransform.Microsoft.AlphaImageLoader-Google-搜索_1264941161008.png"><img src="http://blog.upsuper.org/wp-content/uploads/2010/01/filterprogidDXImageTransform.Microsoft.AlphaImageLoader-Google-搜索_1264941161008-163x300.png" alt="" title="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader - Google 搜索_1264941161008" width="163" height="300" class="alignnone size-medium wp-image-995" /></a></div>
<p>请认真对比我的关键词和两个引擎的结果，你会发现：百度第一页没一个是我要找的，甚至连一个完整匹配的关键词都没有！难道是我的关键词是我瞎编的？不，你看 Google 的结果吧……嗯……事实胜于雄辩，百度众自重……</p>
<p>整个网站的代码，可能在经过完善以后会公布，也可能不公布。由于这次的东西不是做给自己的，所以不能完全我自己说的算了……</p>
<p>参考资料：</p>
<ul>
<li><a href="http://code.google.com/intl/zh-CN/apis/maps/">Google 地图 API &#8211; Google 代码</a></li>
<li><a href="https://groups.google.com/group/Google-Maps-API/msg/8222b18e7921f6e6">What type of map projection does Google use for Google Maps &#8211; Google Groups</a></li>
<li><a href="http://mathworld.wolfram.com/MercatorProjection.html">Mercator Projection &#8212; from Wolfram MathWorld</a></li>
<li><a href="http://www.maxmind.com/app/city_accuracy">MaxMind &#8211; GeoIP City Accuracy for Selected Countries</a></li>
<li><a href="http://apiwiki.twitter.com/">Twitter API Wiki</a> (请自备专用工具访问)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/a-small-site-for-haiti/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>人人网的好友交集小工具</title>
		<link>http://blog.upsuper.org/a-tool-to-get-intersection-of-friends-in-renren/</link>
		<comments>http://blog.upsuper.org/a-tool-to-get-intersection-of-friends-in-renren/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 05:06:30 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[CGI]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[人人网]]></category>
		<category><![CDATA[我的实验室]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=952</guid>
		<description><![CDATA[昨晚花了几个小时写了个计算人人网（其实我还是更喜欢叫他校内）当中，任意两个用户的好友之间交集的在线小工具，可以到我的实验室里看看这个小工具：人人网好友交集。 话说能写出这样的工具，主要有赖于我的空间提供商将系统换为 FreeBSD 后可以解析 Python 了，而且也没有限制 CGI，所以就成功了~ 由于必须从人人网，而非本地，的用户页面，而非接口，获取数据，速度自然不可能快。所以我才有了那个提示：这一过程可能非常缓慢。不过事实上，经过测试，在我的网站的服务器上，速度还是相当了得的，基本上 2s-5s 就能出结果！想我自己的机子上好的时候都要 7s，不好的时候就根本出不来了…… 如果单线程进行获取，那就真可以等死人了……所以用了5线程并发，每个线程维护一个链接……此外还连接的是手机人人网，以换来较小的传输流量，较快的解析速度，和较容易的处理方式…… 最后，看代码之前声明一下，这个是以 AGPLv3 协议发布的，根据这一协议，如果你修改了这个代码并且使用你修改过的代码为他人服务，你所修改的代码也必须公开，并且以 AGPLv3 协议发布。 由于前台界面的东西大家都有办法获取，我就不给了，这里直接给出那个后台处理程序： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 [...]]]></description>
			<content:encoded><![CDATA[<p>昨晚花了几个小时写了个计算人人网（其实我还是更喜欢叫他校内）当中，任意两个用户的好友之间交集的在线小工具，可以到<a href="http://lab.upsuper.org">我的实验室</a>里看看这个小工具：<a href="http://lab.upsuper.org/urenren/">人人网好友交集</a>。</p>
<p>话说能写出这样的工具，主要有赖于我的空间提供商将系统换为 FreeBSD 后可以解析 Python 了，而且也没有限制 CGI，所以就成功了~<br />
<span id="more-952"></span><br />
由于必须从人人网，而非本地，的用户页面，而非接口，获取数据，速度自然不可能快。所以我才有了那个提示：这一过程可能非常缓慢。不过事实上，经过测试，在我的网站的服务器上，速度还是相当了得的，基本上 2s-5s 就能出结果！想我自己的机子上好的时候都要 7s，不好的时候就根本出不来了……</p>
<p>如果单线程进行获取，那就真可以等死人了……所以用了5线程并发，每个线程维护一个链接……此外还连接的是手机人人网，以换来较小的传输流量，较快的解析速度，和较容易的处理方式……</p>
<p>最后，看代码之前声明一下，这个是以 <a href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">AGPLv3</a> 协议发布的，根据这一协议，如果你修改了这个代码并且使用你修改过的代码为他人服务，你所修改的代码也必须公开，并且以 AGPLv3 协议发布。</p>
<p>由于前台界面的东西大家都有办法获取，我就不给了，这里直接给出那个后台处理程序：</p>

<div class="wp_codebox"><table><tr id="p95226"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
</pre></td><td class="code" id="p952code26"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: UTF-8 - * -</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Copyright (C) 2010 Upsuper &lt;quanxunzhen@gmail.com&gt;</span>
<span style="color: #808080; font-style: italic;"># License: AGPLv3</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">threading</span> <span style="color: #ff7700;font-weight:bold;">import</span> Thread, Lock
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">httplib</span> <span style="color: #ff7700;font-weight:bold;">import</span> HTTPConnection
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">cgi</span>, json
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>, <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># 常数设置</span>
THREADS_NUM = <span style="color: #ff4500;">5</span>             <span style="color: #808080; font-style: italic;"># 最大线程数</span>
RENREN_USER = <span style="color: #483d8b;">''</span>            <span style="color: #808080; font-style: italic;"># 人人网用户名</span>
RENREN_PWD  = <span style="color: #483d8b;">''</span>            <span style="color: #808080; font-style: italic;"># 人人网密码</span>
USER_AGENT  = <span style="color: #483d8b;">'urenren 0.1'</span> <span style="color: #808080; font-style: italic;"># 提交给人人网的 User-Agent</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># JSON 输出函数</span>
json_dump = <span style="color: #ff7700;font-weight:bold;">lambda</span> v: json.<span style="color: black;">dump</span><span style="color: black;">&#40;</span>v, <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># 编译匹配用正则表达式</span>
parse_re = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'&lt;td&gt;&lt;p&gt;&lt;a href=&quot;[^<span style="color: #000099; font-weight: bold;">\?</span>]+<span style="color: #000099; font-weight: bold;">\?</span>id=(<span style="color: #000099; font-weight: bold;">\d</span>+)[^&quot;]*&quot;&gt;'</span>
                      r<span style="color: #483d8b;">'&lt;img src=&quot;([^&quot;]+)&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;'</span>
                      r<span style="color: #483d8b;">'&lt;a href=&quot;[^&quot;]+&quot;&gt;([^&lt;]+)&lt;/a&gt;&lt;/td&gt;'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> RequestThread<span style="color: black;">&#40;</span>Thread<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">id</span>, sid, friends<span style="color: black;">&#41;</span>:
    Thread.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.__page = <span style="color: #483d8b;">'/getfriends.do?curpage=%%d&amp;id=%d&amp;sid=%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">id</span>, sid<span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.__friends = friends
    <span style="color: #008000;">self</span>.__conn = HTTPConnection<span style="color: black;">&#40;</span><span style="color: #483d8b;">'3g.renren.com'</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">global</span> curpage, stop_sign
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> stop_sign:
      <span style="color: #808080; font-style: italic;"># 获取当前页面</span>
      curpage_lock.<span style="color: black;">acquire</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
      page = curpage
      curpage += <span style="color: #ff4500;">1</span>
      curpage_lock.<span style="color: black;">release</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
      <span style="color: #808080; font-style: italic;"># 连接获取数据</span>
      conn = <span style="color: #008000;">self</span>.__conn
      conn.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'GET'</span>, <span style="color: #008000;">self</span>.__page <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>page, <span style="color: black;">&#41;</span>, <span style="color: #008000;">None</span>, <span style="color: black;">&#123;</span>
        <span style="color: #483d8b;">'User-Agent'</span>: USER_AGENT
      <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
      data = conn.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
      <span style="color: #808080; font-style: italic;"># 处理获取的数据</span>
      friend_iter = parse_re.<span style="color: black;">finditer</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
      t_stop_sign = <span style="color: #008000;">True</span>
      <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> friend_iter:
        t_stop_sign = <span style="color: #008000;">False</span>
        <span style="color: #008000;">id</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>f.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.__friends<span style="color: black;">&#91;</span><span style="color: #008000;">id</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#40;</span>f.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>, f.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
      stop_sign = t_stop_sign
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> readFriends<span style="color: black;">&#40;</span><span style="color: #008000;">id</span><span style="color: black;">&#41;</span>:
  <span style="color: #808080; font-style: italic;"># 初始化多线程</span>
  <span style="color: #ff7700;font-weight:bold;">global</span> curpage, curpage_lock, stop_sign
  curpage = <span style="color: #ff4500;">0</span>
  curpage_lock = Lock<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  stop_sign = <span style="color: #008000;">False</span>
  threads = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
  friends = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># 创建线程</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span>THREADS_NUM<span style="color: black;">&#41;</span>:
    threads.<span style="color: black;">append</span><span style="color: black;">&#40;</span>RequestThread<span style="color: black;">&#40;</span><span style="color: #008000;">id</span>, sid, friends<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
  <span style="color: #808080; font-style: italic;"># 开始执行线程</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> threads:
    t.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #808080; font-style: italic;"># 等待线程结束</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> threads:
    t.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">return</span> friends
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  <span style="color: #808080; font-style: italic;"># 初始化CGI输出</span>
  <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Content-Type: text/plain'</span>
  <span style="color: #ff7700;font-weight:bold;">print</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># 获取ID信息</span>
  form = <span style="color: #dc143c;">cgi</span>.<span style="color: black;">FieldStorage</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  id1, id2 = <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> form.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id1'</span><span style="color: black;">&#41;</span>: id1 = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>form<span style="color: black;">&#91;</span><span style="color: #483d8b;">'id1'</span><span style="color: black;">&#93;</span>.<span style="color: black;">value</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> form.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id2'</span><span style="color: black;">&#41;</span>: id2 = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>form<span style="color: black;">&#91;</span><span style="color: #483d8b;">'id2'</span><span style="color: black;">&#93;</span>.<span style="color: black;">value</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: black;">&#40;</span>id1 <span style="color: #ff7700;font-weight:bold;">and</span> id2<span style="color: black;">&#41;</span>:
    json_dump<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'error'</span>: <span style="color: #008000;">True</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># 登入人人网</span>
  conn = HTTPConnection<span style="color: black;">&#40;</span><span style="color: #483d8b;">'3g.renren.com'</span><span style="color: black;">&#41;</span>
  conn.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'POST'</span>, <span style="color: #483d8b;">'/login.do'</span>,
      <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlencode</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'email'</span>: RENREN_USER, <span style="color: #483d8b;">'password'</span>: RENREN_PWD<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>,
      <span style="color: black;">&#123;</span>
        <span style="color: #483d8b;">'Content-Type'</span>: <span style="color: #483d8b;">'application/x-www-form-urlencoded'</span>,
        <span style="color: #483d8b;">'User-Agent'</span>: USER_AGENT,
      <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
  response = conn.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  data = response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  conn.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  match = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'sid=([0-9a-f]+)'</span>, data, <span style="color: #dc143c;">re</span>.<span style="color: black;">I</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">global</span> sid
  sid = match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># 读取好友</span>
  friends1 = readFriends<span style="color: black;">&#40;</span>id1<span style="color: black;">&#41;</span>
  friends2 = readFriends<span style="color: black;">&#40;</span>id2<span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>friends1<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>friends2<span style="color: black;">&#41;</span>:
    friends1, friends2 = friends2, friends1
&nbsp;
  <span style="color: #808080; font-style: italic;"># 判断交集</span>
  intersection = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> friends1.<span style="color: black;">iterkeys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> i <span style="color: #ff7700;font-weight:bold;">in</span> friends2:
      intersection.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>i, friends2<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, friends2<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
  json_dump<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'error'</span>: <span style="color: #008000;">False</span>, <span style="color: #483d8b;">'count'</span>: <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>intersection<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'data'</span>: intersection<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
  <span style="color: #ff7700;font-weight:bold;">try</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">except</span>:
    json_dump<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'error'</span>: <span style="color: #008000;">True</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>代码中的配置常数 RENREN_USER 必须是一个已有的人人网账户的帐户名或邮箱地址，反正就是可以用来登入人人网的东西，RENREN_PWD 也必须是前面的账户对应的密码。因为人人网不允许未登入用户查看各种页面（大约是为了防止搜索引擎的人肉吧……不过其实我们有办法让搜索引擎索引到那些内容的~嘿嘿，突然有了一些邪恶的想法~），所以只能弄一个帐号来登入了。</p>
<p>人人网的手机版为了适应部分手机浏览器不支持 Cookies，用了 SID 的策略，这样我也就可以放心大胆地不管 Cookies 了~这个程序还是蛮好写的说~也只有 Python 能提供如此快速的程序构建~</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/a-tool-to-get-intersection-of-friends-in-renren/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>鼠标控制音乐播放的小程序</title>
		<link>http://blog.upsuper.org/a-little-program-for-music-player-control-by-mouse/</link>
		<comments>http://blog.upsuper.org/a-little-program-for-music-player-control-by-mouse/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 12:06:03 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[D-Bus]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[Netbook]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[音乐]]></category>
		<category><![CDATA[鼠标]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=895</guid>
		<description><![CDATA[看这个标题一定很奇怪：难道我以前控制音乐播放不用鼠标么？这个文章的标题看起来像鼠标刚刚发明的推广期的文章……不过，当然不是这样的！ 其实只是想：如何把我的小本合上放书架上，当作一个音乐播放器+功放，并用我的无线6键鼠当遥控器遥控控制之。 想想其实还是蛮有意义的功能，这样我做作业的时候可以不用戴耳机，不用用MP3，直接把本当播放器；同时，我不会看到屏幕上的东西，可以安心做作业~再看看我的6键无限鼠，那额外的功能键平时根本不用，也想不出能有什么用……这么好的东西就这样被我浪费了……（话说，拿本当音乐播放器是不是更浪费？） 说干就干！ 首先提出构想：左键用于暂停和播放，滚轮调节音量，侧边的两个功能键用来切换上一首和下一首。至于右键和中键……再说吧，说不定以后可以扩展更多功能？说不定以后高兴了弄个鼠标手势什么的~嘿嘿 接下来查找资料。印象中我的 Audacious 是可以用 D-Bus 控制的。简单地查阅了一下相关资料，发现了一个叫做 MPRIS 的播放器控制接口。为此，我还专门学习了一下 python-dbus 的使用。 插一句话：python-dbus 怎么没有中文教程啊！英文教程看得还是蛮吃力的…… 连接播放器的代码很简单： 1 2 3 import dbus bus = dbus.SessionBus&#40;&#41; player = bus.get_object&#40;'org.mpris.audacious', '/Player'&#41; 其中 org.mpris.audacious 指的是 audacious，支持 MPRIS 的其他播放器还可以有如下： org.mpris.bmp org.mpris.vlc org.mpris.xmms2 至于那个 /Player 指的是我们要获取的是一个叫 Player 的对象，用于控制播放器。在 MPRIS 中除了 Player 以外，还有根对象 (&#8216;/&#8217;) 和 TrackList 对象 (&#8216;/TrackList&#8217;) 两个，具体的用法其文档里详细说明。这里我只用到了 Player 对象…… [...]]]></description>
			<content:encoded><![CDATA[<p>看这个标题一定很奇怪：难道我以前控制音乐播放不用鼠标么？这个文章的标题看起来像鼠标刚刚发明的推广期的文章……不过，当然不是这样的！</p>
<p>其实只是想：如何把我的小本合上放书架上，当作一个音乐播放器+功放，并用我的无线6键鼠当遥控器遥控控制之。</p>
<p>想想其实还是蛮有意义的功能，这样我做作业的时候可以不用戴耳机，不用用MP3，直接把本当播放器；同时，我不会看到屏幕上的东西，可以安心做作业~再看看我的6键无限鼠，那额外的功能键平时根本不用，也想不出能有什么用……这么好的东西就这样被我浪费了……（话说，拿本当音乐播放器是不是更浪费？）</p>
<p>说干就干！<br />
<span id="more-895"></span><br />
首先提出构想：左键用于暂停和播放，滚轮调节音量，侧边的两个功能键用来切换上一首和下一首。至于右键和中键……再说吧，说不定以后可以扩展更多功能？说不定以后高兴了弄个鼠标手势什么的~嘿嘿</p>
<p>接下来查找资料。印象中我的 Audacious 是可以用 D-Bus 控制的。简单地查阅了一下相关资料，发现了一个叫做 <a href="http://wiki.xmms2.xmms.se/wiki/Media_Player_Interfaces">MPRIS</a> 的播放器控制接口。为此，我还专门学习了一下 <a href="http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html">python-dbus</a> 的使用。</p>
<p>插一句话：python-dbus 怎么没有中文教程啊！英文教程看得还是蛮吃力的……</p>
<p>连接播放器的代码很简单：</p>

<div class="wp_codebox"><table><tr id="p89538"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p895code38"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> dbus
bus = dbus.<span style="color: black;">SessionBus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
player = bus.<span style="color: black;">get_object</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'org.mpris.audacious'</span>, <span style="color: #483d8b;">'/Player'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>其中 org.mpris.audacious 指的是 audacious，支持 MPRIS 的其他播放器还可以有如下：</p>
<ul>
<li>org.mpris.bmp</li>
<li>org.mpris.vlc</li>
<li>org.mpris.xmms2</li>
</ul>
<p>至于那个 /Player 指的是我们要获取的是一个叫 Player 的对象，用于控制播放器。在 MPRIS 中除了 Player 以外，还有根对象 (&#8216;/&#8217;) 和 TrackList 对象 (&#8216;/TrackList&#8217;) 两个，具体的用法其文档里详细说明。这里我只用到了 Player 对象……</p>
<p>看看 Player 对象的方法还挺多，这里我用了这几个：</p>
<ul>
<li>Next() &#8211; 切换到下一首歌曲</li>
<li>Prev() &#8211; 切换到上一首歌曲</li>
<li>Pause() &#8211; 暂停/继续</li>
<li>Play() &#8211; 播放歌曲</li>
<li>VolumeGet() &#8211; 获取当前音量</li>
<li>VolumeSet() &#8211; 设置音量</li>
</ul>
<p>根据前面写的需求，这些已经足够了~</p>
<p>怎么用这些？很简单嘛！就像平时在 Python 里面调用类的方法一样~类型转换？不，那完全不需要你关心！</p>
<p>Python 程序拥有控制播放器的能力了，可是鼠标呢？如何捕获鼠标的动作呢？</p>
<p>想想……屏幕都关了……你还能指望他为你显示什么呢？干脆建立一个窗口把整个屏幕盖住算了！然后让他截获鼠标事件。</p>
<p>快速学习了一下 pygtk 的用法（其实就是照着 Hello World 打了一遍），差不多就知道怎么用了。窗口的建立代码大约如下：</p>

<div class="wp_codebox"><table><tr id="p89539"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p895code39"><pre class="python" style="font-family:monospace;">window = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">fullscreen</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>这段代码很好理解了，第一行就是创建窗口对象，第二行令其全屏，第三行设置其显示，第四行开始 GTK 的主循环。</p>
<p>下面就是鼠标事件的问题了~添加事件用的是类似下面的代码：</p>

<div class="wp_codebox"><table><tr id="p89540"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p895code40"><pre class="python" style="font-family:monospace;">window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'key-press-event'</span>, key_press<span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'destroy'</span>, <span style="color: #ff7700;font-weight:bold;">lambda</span> widget, data = <span style="color: #008000;">None</span>: gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>第一个是注册了键盘按键的事件捕获，将 key-press-event 事件绑定上 key_press 这个函数，而把窗口的销毁事件 destroy 连接到退出 GTK 主循环。说一句废话，连接事件的语句要放在 gtk.main() 之前……key_press 主要用来实现当点击 escape 时退出：</p>

<div class="wp_codebox"><table><tr id="p89541"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p895code41"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> key_press<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> gdk.<span style="color: black;">keyval_name</span><span style="color: black;">&#40;</span>event.<span style="color: black;">keyval</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'Escape'</span>:
    window.<span style="color: black;">destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>好了，下面是鼠标点击事件 button-press-event：</p>

<div class="wp_codebox"><table><tr id="p89542"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p895code42"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> button_press<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">print</span> event
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-press-event'</span>, button_press<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>试试？不行的！差了一番后，发现 Window 这个东西默认是不打开鼠标点击的事件捕获的，逼近大家很少会点窗口本身，都是点里面的按钮什么的……下面的代码要求窗口打开鼠标点击事件的捕获：</p>

<div class="wp_codebox"><table><tr id="p89543"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p895code43"><pre class="python" style="font-family:monospace;">window.<span style="color: black;">add_events</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON_PRESS_MASK</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>接下来就可以了~event.button 表示的是点击的键是哪个。检查了一下，左键是1，右键是3，中键是2，功能键1是8，功能键2是9。滚轮呢？</p>
<p>原来滚轮有自己的事件 scroll。</p>

<div class="wp_codebox"><table><tr id="p89544"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p895code44"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> scroll<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">print</span> event
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'scroll-event'</span>, scroll<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>直接可以用了。识别滚轮方向的是 event.direction，应该是 gtk.gdk.SCROLL_UP、SCROLL_DOWN、SCROLL_LEFT、SCROLL_RIGHT 其中的一个。</p>
<p>下面根据最初的设想，把他们都拼起来就形成了最初的版本：</p>

<div class="wp_codebox"><table><tr id="p89545"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="code" id="p895code45"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> pygtk
pygtk.<span style="color: black;">require</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'2.0'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk
<span style="color: #ff7700;font-weight:bold;">from</span> gtk <span style="color: #ff7700;font-weight:bold;">import</span> gdk
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> dbus
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> button_press<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  button = event.<span style="color: black;">button</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> button == <span style="color: #ff4500;">1</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> player.<span style="color: black;">GetStatus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">2</span>:
      player.<span style="color: black;">Play</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      player.<span style="color: black;">Pause</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> button == <span style="color: #ff4500;">9</span>:
    player.<span style="color: black;">Prev</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> button == <span style="color: #ff4500;">8</span>:
    player.<span style="color: black;">Next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> scroll<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">direction</span> == gdk.<span style="color: black;">SCROLL_UP</span>:
    player.<span style="color: black;">VolumeSet</span><span style="color: black;">&#40;</span>player.<span style="color: black;">VolumeGet</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> event.<span style="color: black;">direction</span> == gdk.<span style="color: black;">SCROLL_DOWN</span>:
    player.<span style="color: black;">VolumeSet</span><span style="color: black;">&#40;</span>player.<span style="color: black;">VolumeGet</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> key_press<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> gdk.<span style="color: black;">keyval_name</span><span style="color: black;">&#40;</span>event.<span style="color: black;">keyval</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'Escape'</span>:
    window.<span style="color: black;">destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
bus = dbus.<span style="color: black;">SessionBus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
player = bus.<span style="color: black;">get_object</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'org.mpris.audacious'</span>, <span style="color: #483d8b;">'/Player'</span><span style="color: black;">&#41;</span>
&nbsp;
window = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'destroy'</span>, <span style="color: #ff7700;font-weight:bold;">lambda</span> widget, data = <span style="color: #008000;">None</span>: gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">add_events</span><span style="color: black;">&#40;</span>gdk.<span style="color: black;">BUTTON_PRESS_MASK</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-press-event'</span>, button_press<span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'key-press-event'</span>, key_press<span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'scroll-event'</span>, scroll<span style="color: black;">&#41;</span>
window.<span style="color: black;">fullscreen</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>OK 看起来不错了，也能控制了。可是，作为一个程序员，怎么能不考虑各种意外呢？试想，如果我们控制着控制着，突然，一个不明真相的窗口弹了出来怎么办呢？！这是一个问题……</p>
<p>最容易想到的方法：把这个窗口永久置顶！</p>
<p>事实上也确实找到了这么个方法，就是把窗体注册成 dock。我们知道 dock 是需要永久置顶的~</p>
<p>用如下方法可以让窗体变成 Dock：</p>

<div class="wp_codebox"><table><tr id="p89546"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p895code46"><pre class="python" style="font-family:monospace;">window.<span style="color: black;">set_type_hint</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">WINDOW_TYPE_HINT_DOCK</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>但是问题又来了：dock 似乎没法接受键盘输入。因为 dock 只是形式上覆盖，并且可以拦截一切在他上面发生的鼠标事件，可键盘焦点就未必在他那里了~</p>
<p>那么我们就不要键盘事件了吧~于是我就把键盘退出给删了，改成了双击退出~查了下资料，双击事件也通过 button-press-event 发送的，必须根据 event.type 来判断是单击、双击还是三击。此外，双击和三击中的每一次点击都会引发一次单击事件。</p>
<p>OK，于是我们把 button_press 函数改成下面这样：</p>

<div class="wp_codebox"><table><tr id="p89547"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code" id="p895code47"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> button_press<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: #008000;">type</span> == gdk._2BUTTON_PRESS:
    window.<span style="color: black;">destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> event.<span style="color: #008000;">type</span> == gdk._3BUTTON_PRESS:
    <span style="color: #ff7700;font-weight:bold;">return</span>
  button = event.<span style="color: black;">button</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> button == <span style="color: #ff4500;">1</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> player.<span style="color: black;">GetStatus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">2</span>:
      player.<span style="color: black;">Play</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      player.<span style="color: black;">Pause</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> button == <span style="color: #ff4500;">9</span>:
    player.<span style="color: black;">Prev</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> button == <span style="color: #ff4500;">8</span>:
    player.<span style="color: black;">Next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>然后删掉键盘处理，最后就成了这样：</p>

<div class="wp_codebox"><table><tr id="p89548"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code" id="p895code48"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> pygtk
pygtk.<span style="color: black;">require</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'2.0'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk
<span style="color: #ff7700;font-weight:bold;">from</span> gtk <span style="color: #ff7700;font-weight:bold;">import</span> gdk
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> dbus
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> button_press<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: #008000;">type</span> == gdk._2BUTTON_PRESS:
    window.<span style="color: black;">destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> event.<span style="color: #008000;">type</span> == gdk._3BUTTON_PRESS:
    <span style="color: #ff7700;font-weight:bold;">return</span>
  button = event.<span style="color: black;">button</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> button == <span style="color: #ff4500;">1</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> player.<span style="color: black;">GetStatus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">2</span>:
      player.<span style="color: black;">Play</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      player.<span style="color: black;">Pause</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> button == <span style="color: #ff4500;">9</span>:
    player.<span style="color: black;">Prev</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> button == <span style="color: #ff4500;">8</span>:
    player.<span style="color: black;">Next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> scroll<span style="color: black;">&#40;</span>widget, event, data = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">direction</span> == gdk.<span style="color: black;">SCROLL_UP</span>:
    player.<span style="color: black;">VolumeSet</span><span style="color: black;">&#40;</span>player.<span style="color: black;">VolumeGet</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">elif</span> event.<span style="color: black;">direction</span> == gdk.<span style="color: black;">SCROLL_DOWN</span>:
    player.<span style="color: black;">VolumeSet</span><span style="color: black;">&#40;</span>player.<span style="color: black;">VolumeGet</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
&nbsp;
bus = dbus.<span style="color: black;">SessionBus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
player = bus.<span style="color: black;">get_object</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'org.mpris.audacious'</span>, <span style="color: #483d8b;">'/Player'</span><span style="color: black;">&#41;</span>
&nbsp;
window = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'destroy'</span>, <span style="color: #ff7700;font-weight:bold;">lambda</span> widget, data = <span style="color: #008000;">None</span>: gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">add_events</span><span style="color: black;">&#40;</span>gdk.<span style="color: black;">BUTTON_PRESS_MASK</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-press-event'</span>, button_press<span style="color: black;">&#41;</span>
window.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'scroll-event'</span>, scroll<span style="color: black;">&#41;</span>
window.<span style="color: black;">set_type_hint</span><span style="color: black;">&#40;</span>gdk.<span style="color: black;">WINDOW_TYPE_HINT_DOCK</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">fullscreen</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
window.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>完成了！</p>
<p>以后就可以拿我的小本来当音乐播放器+功放啦~</p>
<p>参考资料：</p>
<ul>
<li><a href="http://wiki.xmms2.xmms.se/wiki/MPRIS">MPRIS &#8211; XMMS2</a></li>
<li><a href="http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html">dbus-python tutorial</a></li>
<li><a href="http://www.pygtk.org/pygtk2tutorial/index.html">PyGTK 2.0 Tutorial</a></li>
<li><a href="http://library.gnome.org/devel/pygtk/stable/">PyGTK 2.0 Reference Manual</a></li>
<li><a href="http://www.daa.com.au/pipermail/pygtk/2004-January/006832.html">[pygtk] how to generate scroll wheel mouse event.</a></li>
<li><a href="http://topic.csdn.net/t/20030910/11/2243673.html">如何让窗口置顶？ Linux/Unix社区 / 程序开发区 &#8211; CSDN社区 community.csdn.net</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/a-little-program-for-music-player-control-by-mouse/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Python 物理实验数据处理类</title>
		<link>http://blog.upsuper.org/python-class-for-physics-experimentation-data-statistics/</link>
		<comments>http://blog.upsuper.org/python-class-for-physics-experimentation-data-statistics/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 09:06:09 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[同济大学]]></category>
		<category><![CDATA[物理]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=866</guid>
		<description><![CDATA[非常无语的，同济大一什么物理理论都没学，需要的高数基础也都没有学过，竟然要我们先学物理实验，而且要处理数据，计算平均值和标准误差什么的，十分麻烦…… 上次处理数据弄了个零碎的小程序来，很麻烦，这次就把他统一编为一个模块，方便以后使用……这个模块里面的说有公式依据是同济大学出版社《物理实验教程》第1版第二章的内容。 如何使用这个模块呢？首先，作为一个 Python 模块，肯定要用 Python…… 然后我用我第一次做实验的部分数据演示一下： 直接输入数据，标准格式输出~ 最后是代码： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 [...]]]></description>
			<content:encoded><![CDATA[<p>非常无语的，同济大一什么物理理论都没学，需要的高数基础也都没有学过，竟然要我们先学物理实验，而且要处理数据，计算平均值和标准误差什么的，十分麻烦……</p>
<p>上次处理数据弄了个零碎的小程序来，很麻烦，这次就把他统一编为一个模块，方便以后使用……这个模块里面的说有公式依据是同济大学出版社《物理实验教程》第1版第二章的内容。</p>
<p>如何使用这个模块呢？首先，作为一个 Python 模块，肯定要用 Python……</p>
<p>然后我用我第一次做实验的部分数据演示一下：<br />
<a href="http://blog.upsuper.org/wp-content/uploads/2009/10/Screenshot-upsuper@upsuper-netbook-external-tju.png"><img src="http://blog.upsuper.org/wp-content/uploads/2009/10/Screenshot-upsuper@upsuper-netbook-external-tju.png" alt="Screenshot-upsuper@upsuper-netbook: ~-external-tju" title="Screenshot-upsuper@upsuper-netbook: ~-external-tju" width="588" height="303" class="alignnone size-full wp-image-867" /></a></p>
<p>直接输入数据，标准格式输出~</p>
<p>最后是代码：</p>

<div class="wp_codebox"><table><tr id="p86650"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
</pre></td><td class="code" id="p866code50"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">math</span>
sqrt = <span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> gen_imet<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> retfunc<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
    ret = func<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">ave</span> = ret.<span style="color: black;">ave</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">u</span> = ret.<span style="color: black;">u</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">digs</span> = ret.<span style="color: black;">digs</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> retfunc
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_digs<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> a == <span style="color: #ff4500;">0</span>: <span style="color: #ff7700;font-weight:bold;">return</span> b
  <span style="color: #ff7700;font-weight:bold;">elif</span> b == <span style="color: #ff4500;">0</span>: <span style="color: #ff7700;font-weight:bold;">return</span> a
  <span style="color: #ff7700;font-weight:bold;">else</span>: <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">min</span><span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> PhyStat:
  <span style="color: #483d8b;">&quot;&quot;&quot;
  物理实验数据
&nbsp;
  PhyStat(ave, u = 0.0, digs = 0)
  ave   表示平均值，如果传入一列数则自动计算平均值及其标准误差
  u     表示标准误差，如果 ave 传入数据列表则此处表示仪器精度
  digs  表示有效数字个数，0 表示不限制
  &quot;&quot;&quot;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, ave, u = <span style="color: #ff4500;">0.0</span>, digs = <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    对于 ave 为数据列表的情况，使用下面公式计算平均值：
    ave = Σx[i] / n
    根据下面公式计算标准误差：
    S = Sqrt(Σ(x[i]-ave)^2 / (n - 1))
    u = Δinst / Sqrt(3)
    U = Sqrt(S^2 + u^2)
    &quot;&quot;&quot;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">digs</span> = digs
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>ave, <span style="color: #008000;">tuple</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>ave, <span style="color: #008000;">list</span><span style="color: black;">&#41;</span>:
      data = ave
      n = <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
      ave = <span style="color: #dc143c;">math</span>.<span style="color: black;">fsum</span><span style="color: black;">&#40;</span>ave<span style="color: black;">&#41;</span> / n
      <span style="color: #008000;">self</span>.<span style="color: black;">ave</span> = ave
&nbsp;
      s = <span style="color: #ff4500;">0.0</span>
      <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> data:
        s += <span style="color: black;">&#40;</span>i - ave<span style="color: black;">&#41;</span> <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span>
      s = sqrt<span style="color: black;">&#40;</span>s / <span style="color: black;">&#40;</span>n - <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
      u /= sqrt<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
      <span style="color: #008000;">self</span>.<span style="color: black;">u</span> = sqrt<span style="color: black;">&#40;</span>s <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span> + u <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      <span style="color: #008000;">self</span>.<span style="color: black;">ave</span> = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>ave<span style="color: black;">&#41;</span>
      <span style="color: #008000;">self</span>.<span style="color: black;">u</span> = <span style="color: #008000;">abs</span><span style="color: black;">&#40;</span><span style="color: #008000;">float</span><span style="color: black;">&#40;</span>u<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__repr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    ave = <span style="color: #008000;">self</span>.<span style="color: black;">ave</span>
    exp = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">floor</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">log10</span><span style="color: black;">&#40;</span>ave<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    exp10 = <span style="color: #ff4500;">10</span> <span style="color: #66cc66;">**</span> exp
    ave = ave / exp10
    u = <span style="color: #008000;">self</span>.<span style="color: black;">u</span> / exp10
    digs = <span style="color: #008000;">self</span>.<span style="color: black;">digs</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> digs == <span style="color: #ff4500;">0</span>:
      ret = <span style="color: #483d8b;">'%f ±%f'</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      ret = <span style="color: #483d8b;">'%%.%df ±%%.%df'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>digs, digs<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> exp:
      ret = <span style="color: #483d8b;">'(%s) E %d'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>ret, exp<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> ret <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>ave, u<span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #0000cd;">__neg__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: PhyStat<span style="color: black;">&#40;</span>-<span style="color: #008000;">self</span>.<span style="color: black;">ave</span>, <span style="color: #008000;">self</span>.<span style="color: black;">u</span>, <span style="color: #008000;">self</span>.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__pos__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #008000;">self</span>
  <span style="color: #0000cd;">__abs__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: PhyStat<span style="color: black;">&#40;</span><span style="color: #008000;">abs</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ave</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">u</span>, <span style="color: #008000;">self</span>.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__add__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, PhyStat<span style="color: black;">&#41;</span>:
      ave = <span style="color: #008000;">self</span>.<span style="color: black;">ave</span> + other.<span style="color: black;">ave</span>
      u = sqrt<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span> <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span> + other.<span style="color: black;">u</span> <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
      digs = get_digs<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">digs</span>, other.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">return</span> PhyStat<span style="color: black;">&#40;</span>ave, u, digs<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      ave = <span style="color: #008000;">self</span>.<span style="color: black;">ave</span> + other
      <span style="color: #ff7700;font-weight:bold;">return</span> PhyStat<span style="color: black;">&#40;</span>ave, <span style="color: #008000;">self</span>.<span style="color: black;">u</span>, <span style="color: #008000;">self</span>.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #0000cd;">__radd__</span> = <span style="color: #0000cd;">__add__</span>
  <span style="color: #0000cd;">__sub__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: <span style="color: #008000;">self</span> + <span style="color: black;">&#40;</span>-other<span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__rsub__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: other + <span style="color: black;">&#40;</span>-<span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__mul__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, PhyStat<span style="color: black;">&#41;</span>:
      a = <span style="color: #008000;">self</span>.<span style="color: black;">ave</span>
      b = other.<span style="color: black;">ave</span>
      ave = a <span style="color: #66cc66;">*</span> b
      u = ave <span style="color: #66cc66;">*</span> sqrt<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span> / a<span style="color: black;">&#41;</span> <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span> + <span style="color: black;">&#40;</span>other.<span style="color: black;">u</span> / b<span style="color: black;">&#41;</span> <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
      digs = get_digs<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">digs</span>, other.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">return</span> PhyStat<span style="color: black;">&#40;</span>ave, u, digs<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      ave = <span style="color: #008000;">self</span>.<span style="color: black;">ave</span> <span style="color: #66cc66;">*</span> other
      u = <span style="color: #008000;">self</span>.<span style="color: black;">u</span> <span style="color: #66cc66;">*</span> other
      <span style="color: #ff7700;font-weight:bold;">return</span> PhyStat<span style="color: black;">&#40;</span>ave, u, <span style="color: #008000;">self</span>.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #0000cd;">__rmul__</span> = <span style="color: #0000cd;">__mul__</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__div__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, PhyStat<span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span> <span style="color: #66cc66;">*</span> other <span style="color: #66cc66;">**</span> -<span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
      <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">1.0</span> / other<span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #008000;">self</span>
&nbsp;
  <span style="color: #0000cd;">__rdiv__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: other <span style="color: #66cc66;">*</span> <span style="color: #008000;">self</span> <span style="color: #66cc66;">**</span> -<span style="color: #ff4500;">1</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__pow__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
    a = <span style="color: #008000;">self</span>.<span style="color: black;">ave</span>
    ave = a <span style="color: #66cc66;">**</span> other
    u = <span style="color: #008000;">abs</span><span style="color: black;">&#40;</span>other <span style="color: #66cc66;">*</span> <span style="color: #008000;">self</span>.<span style="color: black;">u</span> / a <span style="color: #66cc66;">*</span> ave<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> PhyStat<span style="color: black;">&#40;</span>ave, u, <span style="color: #008000;">self</span>.<span style="color: black;">digs</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #0000cd;">__iadd__</span> = gen_imet<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: <span style="color: #008000;">self</span> + other<span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__isub__</span> = gen_imet<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: <span style="color: #008000;">self</span> - other<span style="color: black;">&#41;</span>
  __imul__ = gen_imet<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: <span style="color: #008000;">self</span> <span style="color: #66cc66;">*</span> other<span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__idiv__</span> = gen_imet<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: <span style="color: #008000;">self</span> / other<span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__ipow__</span> = gen_imet<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, other: <span style="color: #008000;">self</span> <span style="color: #66cc66;">**</span> other<span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #0000cd;">__int__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ave</span><span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__long__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #008000;">long</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ave</span><span style="color: black;">&#41;</span>
  <span style="color: #0000cd;">__float__</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #008000;">self</span>.<span style="color: black;">ave</span></pre></td></tr></table></div>

<p>如果大家发现什么 bug，或者有什么改进建议，欢迎提哈~<span id="more-866"></span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/python-class-for-physics-experimentation-data-statistics/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ujudger 0.1 发布</title>
		<link>http://blog.upsuper.org/ujudger-0-1-release/</link>
		<comments>http://blog.upsuper.org/ujudger-0-1-release/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 02:54:48 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[Cena]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[OI]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[ujudger]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=781</guid>
		<description><![CDATA[曾经的曾经，很早很早以前，我发布了一个叫 ujudger-base 0.1 的东西，是用 C++ 写成的简单测评程序，仅能测试程序运行时间和内存耗用（还不准确）。 这次发布的是一个完整的测评机，支持传统题型、交互题和提交答案题，可导出测评结果。整个程序使用 Python 编写，直接把 ujudger.py 复制到待测目录下并编写 config 文件即可测评。 不过现在这个程序只有一个文字界面，非常简陋，而且安全性不佳。但现在正在撰写的 ujudger 1.0 (版本跨越大，意味着变化之巨大……) 将就这些问题有重大改进，敬请期待。 另外，有人询问是否准备让这个测评机与另一个 Windows 下的开源测评机 Cena 兼容。我的回答是，由于设计差异，可能比较困难。对比 Cena 的自定义校验器，ujudger 的自定义校验器更强大，同时 Cena 的校验器可以通过一点简单的修改或加一个脚本外壳就可以在 ujudger 中使用。在 1.0 中计划兼容 Cena 的校验器。至于配置文件，1.0 中配置文件的格式会有较大变动，不过可能可以通过转换程序将 Cena 的配置文件转为 ujudger 的。 我在 Google Code 上开了一个项目，感兴趣的同学可以关注关注~地址：http://ujudger.googlecode.com/ 最后，ujudger 0.1 的下载地址也在 Google Code 上：ujudger.py]]></description>
			<content:encoded><![CDATA[<p>曾经的曾经，很早很早以前，<a href="http://blog.upsuper.org/ujudger-base-0-1-released/">我发布了一个叫 ujudger-base 0.1 的东西</a>，是用 C++ 写成的简单测评程序，仅能测试程序运行时间和内存耗用（还不准确）。</p>
<p>这次发布的是一个完整的测评机，支持传统题型、交互题和提交答案题，可导出测评结果。整个程序使用 Python 编写，直接把 ujudger.py 复制到待测目录下并编写 config 文件即可测评。</p>
<p>不过现在这个程序只有一个文字界面，非常简陋，而且安全性不佳。但现在正在撰写的 ujudger 1.0 (版本跨越大，意味着变化之巨大……) 将就这些问题有重大改进，敬请期待。</p>
<p>另外，有人询问是否准备让这个测评机与另一个 Windows 下的开源测评机 Cena 兼容。我的回答是，由于设计差异，可能比较困难。对比 Cena 的自定义校验器，ujudger 的自定义校验器更强大，同时 Cena 的校验器可以通过一点简单的修改或加一个脚本外壳就可以在 ujudger 中使用。在 1.0 中计划兼容 Cena 的校验器。至于配置文件，1.0 中配置文件的格式会有较大变动，不过可能可以通过转换程序将 Cena 的配置文件转为 ujudger 的。</p>
<p>我在 Google Code 上开了一个项目，感兴趣的同学可以关注关注~地址：<a href="http://ujudger.googlecode.com/">http://ujudger.googlecode.com/</a></p>
<p>最后，ujudger 0.1 的下载地址也在 Google Code 上：<a href="http://ujudger.googlecode.com/files/ujudger.py">ujudger.py</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/ujudger-0-1-release/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>探索 Python 之 变量、类型和引用</title>
		<link>http://blog.upsuper.org/explore-python-variable-type-and-refrence/</link>
		<comments>http://blog.upsuper.org/explore-python-variable-type-and-refrence/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 14:23:15 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[探究学习]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=775</guid>
		<description><![CDATA[我一开始为 Python 的强大和简洁所震撼，看了些 Python 的教程，学了不少东西。前面那些探索就以后再写吧……今天先讲讲今天知道的东西。 在探索到 Python 函数的参数传递的时候，我不禁赞叹 Python 灵活的参数设计，但慢慢的，开始迷惑与传递参数的修改和返回。 众所周知，在 C++ 中传递参数分为传值和传引用两种，但 Python 没有，那到底传进去的东西，修改一下，能不能传出来呢？这是一个很奇怪和让人费解的问题，不是么？在查阅了一些资料后，对 Python 关于变量、类型和引用的一些基本方式有了一些了解，进而基于这种理解并结合实验，了解了参数传递的奥妙。 Python 的变量是没有类型的，这与以往看到的大部分语言都不一样。但 Python 却是区分类型的，那类型在哪里呢？事实是，类型是跟着内存中的对象走的。Python 的所有变量其实都是指向内存中的对象的一个指针，所有的变量都是！此外，对象还分两类：一类是可修改的，一类是不可修改的。 现在，我插入在此先说说函数参数的问题，我们有下面一个实验： 1 2 3 4 5 6 7 8 def func1&#40;a&#41;: a += 1 def func2&#40;a&#41;: a&#91;0&#93; = 0 t1 = 0 func1&#40;t1&#41; print t1 t2 = &#91;1, 2, 3&#93; func2&#40;t2&#41; print t2 [...]]]></description>
			<content:encoded><![CDATA[<p>我一开始为 Python 的强大和简洁所震撼，看了些 Python 的教程，学了不少东西。前面那些探索就以后再写吧……今天先讲讲今天知道的东西。</p>
<p>在探索到 Python 函数的参数传递的时候，我不禁赞叹 Python 灵活的参数设计，但慢慢的，开始迷惑与传递参数的修改和返回。</p>
<p>众所周知，在 C++ 中传递参数分为传值和传引用两种，但 Python 没有，那到底传进去的东西，修改一下，能不能传出来呢？这是一个很奇怪和让人费解的问题，不是么？在查阅了一些资料后，对 Python 关于变量、类型和引用的一些基本方式有了一些了解，进而基于这种理解并结合实验，了解了参数传递的奥妙。<br />
<span id="more-775"></span><br />
Python 的变量是没有类型的，这与以往看到的大部分语言都不一样。但 Python 却是区分类型的，那类型在哪里呢？事实是，类型是跟着内存中的对象走的。Python 的所有变量其实都是指向内存中的对象的一个指针，所有的变量都是！此外，对象还分两类：一类是可修改的，一类是不可修改的。</p>
<p>现在，我插入在此先说说函数参数的问题，我们有下面一个实验：</p>

<div class="wp_codebox"><table><tr id="p77558"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p775code58"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> func1<span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>: a += <span style="color: #ff4500;">1</span>
<span style="color: #ff7700;font-weight:bold;">def</span> func2<span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>: a<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = <span style="color: #ff4500;">0</span>
t1 = <span style="color: #ff4500;">0</span>
func1<span style="color: black;">&#40;</span>t1<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t1
t2 = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
func2<span style="color: black;">&#40;</span>t2<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t2</pre></td></tr></table></div>

<p>结果是：</p>

<div class="wp_codebox"><table><tr id="p77559"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p775code59"><pre class="text" style="font-family:monospace;">0
[0, 2, 3]</pre></td></tr></table></div>

<p>看看结果会不会很惊异？第一个看起来像传值，第二个看起来却像传引用？看到这里你是不是觉得 Python 是一种莫名其妙的语言？其实当时我也有这种想法……但 Python 果然没哟让我失望，它如同 UNIX 一样，一开始设计得就如此优美。继续往下看~</p>
<p>不可修改的对象是我们最常用和最熟悉，几乎在任何一个语言中都能看到的——整数、实数、字符串和元组。有人说，怎么不可变啊？我随便给他们赋值！是的，在 Python 里几乎一切都是可以改变的，甚至有人说“如果你愿意，None 的值也是可以变的”（当然我不知道怎么变……）。但是如果注意观察，会发现所谓的改变其实是——<strong>扔了旧的建个新的！</strong>验证这个的实验很简单：</p>

<div class="wp_codebox"><table><tr id="p77560"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p775code60"><pre class="python" style="font-family:monospace;">a = <span style="color: #ff4500;">1</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>
a += <span style="color: #ff4500;">1</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>类似的实验想怎么做怎么做，只要那两个是不可变对象，你就一定会发现 id 变了！为什么？因为对象不可变。那什么可变？变量的引用是可变的！</p>
<p>好，那么自然剩下的就是可变的对象了，上面的实验亦可以很容易的证实字典、列表、集合和类实例等对象是可变的。那么，这意味着什么呢？</p>
<p>下面，我们回到函数传值的问题。我们知道了可变对象和不可变对象的区别，不是吗？对于可变对象，对于对象的操作不会重建对象，而对于不可变对象，每一次操作就重建新的对象。那么函数参数到底是个什么东西呢？<strong>其实说白了也简单，就是把参数里传入的东西对相应对象的引用依次赋给对应的内部变量</strong>（有点晕吗？）。看看第一个实验，有没有明白些什么？其实都是将一个指向对象的引用传个一个名为“参数”的本地变量，所以 func1 中给 a 的是一个值为 0 的整数对象的引用，但我们知道，整数对象是不可变的，所以当 func1 对 a 进行修改的时候，实际上是修改本地变量 a 的引用到一个新的值为 1 的整数对象的引用。那么很显然，func2 修改的是一个可变的对象，也就是说即使 func2 修改了 a，本地变量 a 和全局变量 t2 指向的还是同一个对象，虽然他们不是同一个变量！这样一切情况都明了了，不是么？不明了的话再看看下面这个实验：</p>

<div class="wp_codebox"><table><tr id="p77561"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p775code61"><pre class="python" style="font-family:monospace;">a = <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
b = a<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
b<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = <span style="color: #ff4500;">0</span>
<span style="color: #ff7700;font-weight:bold;">print</span> a</pre></td></tr></table></div>

<p>输出一定是：</p>

<div class="wp_codebox"><table><tr id="p77562"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p775code62"><pre class="text" style="font-family:monospace;">[[0, 2, 3], [4, 5, 6]]</pre></td></tr></table></div>

<p>其实原理和参数的传递是一致的。</p>
<p>我们下面来看看全局变量和本地变量的问题。如果一个函数里面使用了一个变量，那么 Python 会先看看有没有对应的本地变量，如果没有找到，但找到一个全局变量，那么 Python 会把<strong>那个全局变量的引用赋给一个新的本地变量</strong>。所以，现在在函数里的那个变量和全局变量其实不是同一个变量，他们只不过暂时有了相同的引用。这样其实可以看作 Python 为你做了隐式的参数传递。因此我们发现，他和参数一样，传值传引用表面上看过去漂移不定。那么如何修改一个指向不可变全局变量的值呢？靠返回值显然不那么优美。好在 Python 像 PHP 那样提供了一个叫 global 的语法，被 global 的变量使得<strong>本地变量成为相应全局变量的一个别名</strong>，也就是说这个语句使他们成为同一个变量，这一点很重要！</p>
<p>现在看到了 Python 优美的设计。那下面的问题是，如果我们一定要复制一个可变对象的副本怎么办？简单的等号赋值显然被证明无效了。Python 也提供了方法——copy 模块。copy 模块是每一个 Python 都有的，专门用于生成可变对象的副本。copy 模块中有两个函数：copy.copy 和 copy.deepcopy。其中 copy 叫做潜复制，它仅仅复制了第一你给它的东西，下面的不管了。而 deepcopy 叫做深复制，它将所有能复制的都复制了。这样说比较抽象，我们来看下面实验：</p>

<div class="wp_codebox"><table><tr id="p77563"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p775code63"><pre class="python" style="font-family:monospace;">a = <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
b = a
c = <span style="color: #dc143c;">copy</span>.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>
d = <span style="color: #dc143c;">copy</span>.<span style="color: black;">deepcopy</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>
a.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">15</span><span style="color: black;">&#41;</span>
a<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span> = <span style="color: #ff4500;">10</span>
<span style="color: #ff7700;font-weight:bold;">print</span> a
<span style="color: #ff7700;font-weight:bold;">print</span> b
<span style="color: #ff7700;font-weight:bold;">print</span> c
<span style="color: #ff7700;font-weight:bold;">print</span> d</pre></td></tr></table></div>

<p>输出结果：</p>

<div class="wp_codebox"><table><tr id="p77564"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p775code64"><pre class="text" style="font-family:monospace;">[[1, 2, 3], [4, 5, 10], 15]
[[1, 2, 3], [4, 5, 10], 15]
[[1, 2, 3], [4, 5, 10]]
[[1, 2, 3], [4, 5, 6]]</pre></td></tr></table></div>

<p>我想，效果不言而喻了。</p>
<p>此外，我还看到一个叫做弱引用 (weakref) 的模块，暂时不知道是干嘛的……下次研究了再说……</p>
<p>参考：</p>
<ul>
<li><a href="http://blog.csdn.net/winterTTr/archive/2008/06/27/2590741.aspx">Python的函数参数传递：传值？引用？</a></li>
<li><a href="http://www.jb51.net/article/15714.htm">Python 拷贝对象（深拷贝deepcopy与浅拷贝copy）</a></li>
<li><a href="http://www.cnblogs.com/sislcb/archive/2008/09/05/1284828.html">Python 学习笔记 &#8211; 8.引用(Reference)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/explore-python-variable-type-and-refrence/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

