##language:zh ''' 解决在 Python 中登录网站的问题 ''' -- xyb [<>] <> = 解决在 Python 中登录网站的问题 = {{{ 作者:Xie Yanbo, 版权:创作共用/cc 1.0, 原文地址:http://xie.freezope.org/blog/2004/08/python.html }}} * 所谓登录进入一个网站,实际上就是在浏览器里留下一些暂时或长期的 cookie 而已。 * 如果我们用 Python 访问一些需要登录才能看到的内容,'''只要把登录之后传回来的cookies再传回去就行了。''' == CookieClient == 虽然 Python2.3 提供了 Cookie 这个模块,但做为操作客户端 cookie 来说并不实用。我们也可以靠自己维护 http header 来实现这些功能,但这很很麻烦。还好有人提供了不错的模块,比如 [[http://wwwsearch.sourceforge.net/ClientCookie/|CookieClient]] 就是不错的选择。下面是我用 CookieClient 编写的一个访问 [[http://www.linuxforum.net/|linuxforum]] 的示例脚本: {{{ #!python #!/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") }}} ''下载源代码:[[attachment:lfcookie-1.py]]'' * 这个例子里用的是 ClientCookie-0.9.4a。 == with urllib2 == 不过从 Python2.4 开始,将会增加 [[http://www.python.org/dev/doc/devel/lib/module-cookielib.html|clientlib]] 来提供对客户端 cookie 的支持,其中绝大部分代码都是 ClientCookie 里的,只不过调整了一下组织方式和文档,并且和 urllib2 整合在了一起。把上面的代码翻译一下,就可以得到如下的代码: {{{ #!python #!/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") }}} ''下载源代码:[[attachment:lfcookie-2.py]]'' = 后续 = * 不过现在 Python2.4a2 的 urllib2 还有点 [[http://python.org/sf/996159|bug]],它导致发出的请求 header 会有两个大小写不同的 Content-Length。这也导致我们的这个例子现在还不能正常运行,不过我想等正式的 Python2.4 出来以后这段代码应该能直接执行。 * 另外,在上面的代码中我是使用的 cookielib.LWPCookieJar() 或 ClientCookie.LWPCookieJar(),其实还有 MozillaCookieJar、MSIECookieJar、MSIEDBCookieJar 和 BSDDBCookieJar 这些选择。 * '''2004-09-06''',注:Python2.4a3 发布,clientlib 没有什么问题了,我的那段倒是有问题,一是需要 install_opener,二是需要使用 urllib2.urlopen。现在改过了。 == 2006 == * ZoomQuiet 使用Ubuntu 平台时可用相关参数:{{{ HTTP Request GET /hallo.php HTTP/1.1 User-Agent Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061025 Firefox/2.0 (Swiftfox) Accept text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language en-us,en;q=0.5 Accept-Encoding gzip,deflate Accept-Charset UTF-8,* }}}