2004-08-25

解决在 Python 中登录网站的问题

所谓登录进入一个网站,实际上就是在浏览器里留下一些暂时或长期的 cookie 而已。如果我们用 Python 访问一些需要登录才能看到的内容,只要把登录之后传回来的cookies再传回去就行了。

虽然 Python2.3 提供了 Cookie 这个模块,但做为操作客户端 cookie 来说并不实用。我们也可以靠自己维护 http header 来实现这些功能,但这很很麻烦。还好有人提供了不错的模块,比如 CookieClient 就是不错的选择。下面是我用 CookieClient 编写的一个访问 linuxforum 的示例脚本:

#!/usr/bin/env python
# -*- coding: GB2312 -*-
# xyb at linuxforum.net

import sys
import ClientCookie
from urllib import urlencode

# add loader
cookies = ClientCookie.LWPCookieJar()
opener = ClientCookie.build_opener(
ClientCookie.HTTPCookieProcessor(cookies),
ClientCookie.HTTPRefererProcessor,
ClientCookie.HTTPEquivProcessor,
ClientCookie.HTTPRefreshProcessor,
ClientCookie.SeekableProcessor)
opener.addheaders = [
("User-agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Debian/1.5-3"),
("Accept", "text/html, image/jpeg, image/png, text/*, image/*, */*")]
ClientCookie.install_opener(opener)

# check args
if len(sys.argv) <= 2:
print "Usage: %s USERNAME PASSWORD" % (sys.argv[0])
sys.exit(1)
else:
UserName = sys.argv[1]
Password = sys.argv[2]

# login
data = {
'Loginname': UserName,
'Loginpass': Password,
'firstlogin': 1,
'option': '登入论坛'
}
urldata = urlencode(data)
r = ClientCookie.urlopen("http://www.linuxforum.net/forum/start_page.php", urldata)

# show result
results = r.read()
open('start.html', 'w').write(results)

# then, user page
r = ClientCookie.urlopen("http://www.linuxforum.net/forum/login.php?Cat=")
results = r.read()
open('user.html', 'w').write(results)

# read messages
r = ClientCookie.urlopen("http://www.linuxforum.net/forum/viewmessages.php?Cat=&box=received")
results = r.read()
open('inbox.html', 'w').write(results)

# save cookies to file
cookies.save("./cookies")

这个例子里用的是 ClientCookie-0.9.4a。

不过从 Python2.4 开始,将会增加 clientlib 来提供对客户端 cookie 的支持,其中绝大部分代码都是 ClientCookie 里的,只不过调整了一下组织方式和文档,并且和 urllib2 整合在了一起。把上面的代码翻译一下,就可以得到如下的代码:

#!/usr/bin/env python
# -*- coding: GB2312 -*-
# xyb at linuxforum.net

import sys
from urllib import urlencode
import cookielib, urllib2
cj = cookielib.LWPCookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
opener.addheaders = [
("User-agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Debian/1.5-3"),
("Accept", "text/html, image/jpeg, image/png, text/*, image/*, */*")]

# check args
if len(sys.argv) <= 2:
print "Usage: %s USERNAME PASSWORD" % (sys.argv[0])
sys.exit(1)
else:
UserName = sys.argv[1]
Password = sys.argv[2]

# login
data = {
'Loginname': UserName,
'Loginpass': Password,
'firstlogin': 1,
'option': '登入论坛'
}
urldata = urlencode(data)
r = opener.open("http://www.linuxforum.net/forum/start_page.php", urldata)

# show result
results = r.read()
open('start.html', 'w').write(results)

# then, user page
r = urllib2.urlopen("http://www.linuxforum.net/forum/login.php?Cat=")
results = r.read()
open('user.html', 'w').write(results)

# read messages
r = urllib2.urlopen("http://www.linuxforum.net/forum/viewmessages.php?Cat=&box=received")
results = r.read()
open('inbox.html', 'w').write(results)

# save cookies to file
cj.save("./cookies")

不过现在 Python2.4a2 的 urllib2 还有点 bug,它导致发出的请求 header 会有两个大小写不同的 Content-Length。这也导致我们的这个例子现在还不能正常运行,不过我想等正式的 Python2.4 出来以后这段代码应该能直接执行。

另外,在上面的代码中我是使用的 cookielib.LWPCookieJar() 或 ClientCookie.LWPCookieJar(),其实还有 MozillaCookieJar、MSIECookieJar、MSIEDBCookieJar 和
BSDDBCookieJar 这些选择。

2004-09-06,注:Python2.4a3 发布,clientlib 没有什么问题了,我的那段倒是有问题,一是需要 install_opener,二是需要使用 urllib2.urlopen。现在改过了。

2004-08-21

好多小吃呀,留口水!

中文维基百科最近有一个条目质量提升计划,目标就是把已有的条目做到象模象样。最近几天选中了小吃,一时之间连带小吃列表条目也活跃了起来。今天好好看了看,头一回知道原来全国各地有这么多种小吃,看得我都流口水了,呵呵。你也要小心哦,不要把键盘都打湿了 ;)

笑话:怎样保持婚姻和谐

偶然看到,莞尔之余觉得这个笑话还真是寓意深刻呢 :)


一对夫妇欢度他们的结婚纪念日,他们之间的和谐相处长期以来为人津津乐道。 当地的一位记者于是前去访问他们之所以拥有幸福婚姻的秘诀。

丈夫向记者解释说:“嗯,这就要从我们的蜜月说起了。”

我们到大峡谷度蜜月,原本我们是要骑驴子到峡谷底﹐不过才走了没有多久,我太太的驴子就跌了一跤。 我太太安静的说:“第一次。”

再次上路以后没有多久那只驴子又跌了一跤,我太太又安静的说:“第二次。”

还没有半哩路驴子又跌跤了,这时我太太拔出她的左轮手枪毙了那只驴子。

我很不能认同她的行为,于是开始与她争论,这时,我的新婚妻子安静的对我说:“第一次……”

2004-08-13

在 Python 中生成 tar.bz2 文件

Python Cookbook 中看到一个很有趣的方法来创建 tar.bz2 文件,但他的代码里错误太多了,正确的写法应该是这个样子的:

import tarfile
import os
out = tarfile.TarFile.open('out.tar.bz2', 'w:bz2')
arcpath='/home/xyb/bin/'
out.add(arcpath, arcname=os.path.basename(arcpath))
out.close()

2004-08-02

Doom 3 真的是泄露了

DOOM 3 的泄漏据说已经被证实。咳,ID 这回又痛苦一把。

过了一个晚上,我的DOOM3终于下载下来了。最终下载完成的这个版本 Reloaded 版,就说是 0day 正式认可的版本,包括 Keygen 和 Crack,1.7G呀,要是没有 BT 这东西,怎么可能想象一夜之间全世界都能下载得到!呵呵,不管怎么说,等下了班找台 Windows 试试。不过我可不抱什么幻想,我已经知道很多不错的机器运行起来都很慢,只有 20-30 fps :(

2004-08-01

Doom 3 来了!?

刚看到有人说 0day 拿到了 Doom 3 的母盘,刚听说今天晚上会有 Doom 3 放出,就看到有人放出了 Doom 3 的种子:

http://66.90.75.92/suprnova//torrents/2306/Doom_3_POTUK.torrent
http://torrent.youceff.com/download.php?file=415634

其中第一个我已经开始下载,只是不知道这是不是真的:
$ btshowmetainfo.py Doom_3_POTUK.torrent
btshowmetainfo 20021207 - decode BitTorrent metainfo files

metainfo file.: Doom_3_POTUK.torrent
info hash.....: 2944a3841342e830b07288489e46543e86a5c09a
directory name: Doom 3
files.........:
D3_CD1.ISO (484235264)
D3_CD2.ISO (584992768)
D3_CD3.ISO (557527040)
archive size..: 1626755072 (1551 * 1048576 + 413696)
announce url..: http://www.potuk.org:2710/announce

其实应该支持 ID,去买正版,但是中国的情况……