<?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>Movoin Studio &#187; Python</title>
	<atom:link href="http://www.movoin.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.movoin.com</link>
	<description>专注Web开发, Python和Php技术 &#38;&#38; 关注开源及移动应用</description>
	<lastBuildDate>Wed, 14 Dec 2011 04:02:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Python编写蜘蛛/爬虫</title>
		<link>http://www.movoin.com/python-devel-spider.html</link>
		<comments>http://www.movoin.com/python-devel-spider.html#comments</comments>
		<pubDate>Tue, 18 Jan 2011 01:48:55 +0000</pubDate>
		<dc:creator>Allen</dc:creator>
				<category><![CDATA[程序开发]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[爬虫]]></category>

		<guid isPermaLink="false">http://www.movoin.com/?p=83</guid>
		<description><![CDATA[我目前住在女友家的花场（种花木的花木基地，空气清新并夹杂着混合了泥土味的阵阵猪屎气息，绝对的有益身心），只是美中不足的地方是，由于地方较为偏僻没办法上网。虽然可以通过无线3G上网，但是上网价格明显和工资水平不是一个级别，暂时不考虑。 再说，在花场大部分时间我都不需要用到网络，因为我会把需要用到网络的工作留在公司做，而不需要用到网络的工作才带回花场（比如：设计类、动画类、制作类等）。但有时设计也需要用到素材或是参考一下别的设计的时候，素材倒好办，买DVD或是到电驴上下载回来就行。可是参考设计这个就没有了，于是我就有了一个念头，就是写个爬虫把常用的一些界面设计全部下载到本机来。 非线程版本： #!/usr/bin/python # -*- coding: utf-8 -*- import os, sys import urllib import urllib2 import re from BeautifulSoup import BeautifulSoup import chardet import datetime get_charset = lambda html: chardet.detect(html) abspath = os.path.dirname(__file__) class FC(object): _base_url_ = None _list_params_ = None _urls_ = None _html_ = None _start_page_ = 1 _end_page_ = 1 _current_page_ [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>我目前住在女友家的花场（种花木的花木基地，空气清新并夹杂着混合了泥土味的阵阵猪屎气息，绝对的有益身心），只是美中不足的地方是，由于地方较为偏僻没办法上网。虽然可以通过无线3G上网，但是上网价格明显和工资水平不是一个级别，暂时不考虑。<br />
再说，在花场大部分时间我都不需要用到网络，因为我会把需要用到网络的工作留在公司做，而不需要用到网络的工作才带回花场（比如：设计类、动画类、制作类等）。但有时设计也需要用到素材或是参考一下别的设计的时候，素材倒好办，买DVD或是到电驴上下载回来就行。可是参考设计这个就没有了，于是我就有了一个念头，就是写个爬虫把常用的一些界面设计全部下载到本机来。</p></blockquote>
<p><span id="more-83"></span></p>
<h2>非线程版本：</h2>
<pre name="code" class="sh_python" linenum="off">#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, sys
import urllib
import urllib2
import re

from BeautifulSoup import BeautifulSoup
import chardet

import datetime

get_charset = lambda html: chardet.detect(html)

abspath = os.path.dirname(__file__)

class FC(object):

    _base_url_ = None
    _list_params_ = None

    _urls_ = None
    _html_ = None

    _start_page_ = 1
    _end_page_ = 1
    _current_page_ = 1

    _soup = None

    _begin_time_ = None

    _download_dir_ = 'downloads/'
    _download_list_ = {}

    def __init__(self, base_url, list_param, set_end_page = None):
        """
        构造函数
        """
        self._begin_time_ = datetime.datetime.now()

        self.logging(u'开始运行...')

        (self._base_url_, self._list_params_) = (base_url, list_param)

        if set_end_page == None and set_end_page > 0:
            self.setEndPage()
        else:
            self._end_page_ = int(set_end_page)
            self.logging(u'手动设置列表分页总数为 %d 页...' % set_end_page)

        self.loadListPages()

    def __del__(self):
        """
        析构函数
        """
        self.logging(u'执行时间：%d 秒...' % (datetime.datetime.now() - self._begin_time_).seconds)
        self.logging(u'结束运行...')

    def nextPage(self):
        """
        当前页面递加 1
        """
        self._current_page_ = self._current_page_ + 1

    def setEndPage(self):
        """
        设置列表分页总数
        """
        self.logging(u'获得并设置列表分页总数...')

        html = self.fetchHtml(self.getFirstPageLink())

        pager = self._soup.find('td', attrs={'align': 'center', 'bgcolor': '#FFFFFF', 'class': 't14'}).renderContents()

        if pager:
            href = BeautifulSoup(pager).findAll('a')[-1]['href']

            try:
                count = re.search('\d{2}', href).group()
            except:
                self.logging('Can not fetch pages count!', 'ERROR')

            self._end_page_ = int(count)
        self.logging(u'总共 %d 页...' % self._end_page_)

    def loadListPages(self):
        """
        载入页面列表
        """
        self._urls_ = [(self._base_url_ + (self._list_params_ % i)) for i in range(self._start_page_, (self._end_page_ + 1))]

        self.logging(u'获得所有列表页面URL...')

    def getFirstPageLink(self):
        """
        获得第一页的链接
        """
        return self._base_url_ + (self._list_params_ % self._start_page_)

    def getPageLink(self, page):
        """
        获得页面链接
        """
        return self._base_url_ + page

    def fetchAll(self):
        """
        分析列表
        """
        self.logging(u'开始分析列表...')

        if self._urls_:
            for url in self._urls_:
                self.fetchListHtml(url)
                self.getImgList()
                self.logging(u'分析第 %d 页完成，执行时间：%d 秒...' % (self._current_page_, (datetime.datetime.now() - self._begin_time_).seconds))

                self.nextPage()

                self.logging(u'-----------------------------------------------', 'LINE')
        else:
            self.logging(u'列表堆栈为空，无法分析...', 'WAITTING')

        # 开始下载
        # if self._download_list_:
            # self.logging(u'开始下载图片...')

            # for title in self._download_list_.keys():
                # self.download(self._download_list_[title], title)

        # self.logging(u'下载完成...')

    def fetchListHtml(self, url):
        """
        获得列表页HTML
        """
        self._soup = None

        self.logging(u'开始采集第 %d 页的数据...' % self._current_page_)

        try:
            html = urllib.urlopen(url).read()
            self._soup = BeautifulSoup(html, fromEncoding='utf-8')
            self._html_ = self._soup.find('table',  attrs={'width': '96%', 'bgcolor': '#efefef', 'cellspacing': '0', 'cellpadding': '0', 'border': '0'}).prettify()
            self._html_ = self._encoding(self._html_)
        except:
            self.logging(u'采集 %s 的数据失败...' % url, 'WAITTING')

        html = None
        return self._html_

    def fetchHtml(self, url, is_prettify = True):
        """
        获得页面HTML
        """
        self._soup = None

        self.logging(u'抓取 %s 的数据...' % url)

        try:
            html = self.fetch(url)
            self._soup = BeautifulSoup(html, fromEncoding='utf-8')
            if is_prettify:
                self._html_ = self._soup.prettify()
                self._html_ = self._encoding(self._html_)
            else:
                self._html_ = self._soup
        except:
            self.logging(u'采集 %s 的数据失败...' % url, 'WAITTING')

        html = None
        return self._html_

    def fetch(self, url):
        """
        获取内容
        """
        try:
            opener = urllib2.build_opener(urllib2.HTTPHandler)
            opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3')]
            opener.addheaders = [('Referer', 'http://www.68design.net/')]
            urllib2.install_opener(opener)
            response = urllib2.urlopen(url)

            return response.read()
        except:
            self.logging(u'采集 %s 的数据失败...' % url, 'WAITTING')

    def getImgList(self):
        """
        获得图片列表
        """
        self.logging(u'开始获取第 %d 页的图片URL...' % self._current_page_)

        try:
            tables = self._soup.findAll('table', attrs={'width': '116', 'align': 'center', 'cellspacing': '0', 'cellpadding': '0', 'border': '0'})
        except:
            self.logging(u'获取失败...', 'WAITTING')

        if tables:
            self.logging(u'总共获得 %s 条地址' % len(tables))

            for table in tables:
                link = table.find('a', attrs={'class': 'a04'})['href']

                """
                获得列表中的图片
                """
                page = self.fetchHtml(self.getPageLink(link), False)

                try:
                    # 标题
                    title = page.find('td', attrs={'height': '65', 'align': 'center', 'valign': 'bottom', 'class': 't25'}).contents[0]
                    self.logging(u'获取图片标题为 [%s]...' % title)
                    # 分页
                    pagerSoup = page.find('td', attrs={'align': 'center', 'class': 't14', 'width': None, 'height': None})
                except:
                    self.logging(u'获取图片标题失败...', 'WAITTING')

                links = self.getImgsPager(pagerSoup)

                if links:
                   imgList = [self.getPageLink(link)] + [self._base_url_ + link for link in links]
                else:
                   imgList = [self.getPageLink(link)]

                self._download_list_[title] = self.getImgs(imgList)

    def getImgs(self, links):
        """
        获得页面中的图片
        """
        imgs = []

        if links:
            for link in links:
                page = self.fetchHtml(link, False)

                try:
                    imgs.append(page.find('img', attrs={'onload': 'resizepic(this)'})['src'])
                except:
                    self.logging(u'获取图片地址失败...', 'WAITTING')

        return imgs

    def getImgsPager(self, pager = None):
        """
        获得列表中图片的内容分页列表
        """
        if pager:
            # 清除重复链接(下一页，上一页，尾页)
            return [str(link['href']) for link in pager.findAll('a') if re.search('[\d{1|2}]', link.string)]

        return None

    def download(self, lists, title):
        """
        下载图片文件
        """
        path = os.path.join(abspath, self._download_dir_, title)

        if title:
            if os.path.exists(path) == False:
                os.mkdir(path)

        if lists:
            for url in lists:
                try:
                    data = self.fetch(url)
                except:
                    self.logging(u'图片 %s 无法下载...' % url, 'WAITTING')

                suffix = url[-3:]
                filename = 'image-' + str(lists.index(url) + 1) + '.' + suffix

                try:
                    f = file(os.path.join(path, filename), 'wb')
                    f.write(data)
                    f.close()

                    self.logging(u'写入 [%s] 文件完成...' % filename)
                except:
                    self.logging(u'写入 [%s] 文件失败...' % filename, 'WAITTING')

    def _encoding(self, html):
        """
        转换编码
        """
        charset = get_charset(html)
        if charset['encoding'] == 'utf-8':
            html = unicode(html, 'utf-8', 'ignore').encode('gbk', 'ignore')

        return html

    def logging(self, msg, type = 'INFO'):
        """
        输出格式化日志
        """
        print '[%s] - %s (%s)' % (type, msg, datetime.datetime.now())

def main():
    fc = FC('http://www.68design.net/Appreciate/Interface/', 'list-%d.html', 1)
    fc.fetchAll()

    #lists = fc.getImgs(['http://www.68design.net/Appreciate/Interface/55303-1.html'])
    #fc.download(lists, 'hello')

if __name__ == '__main__':
    main()
</pre>
<h2>说明：</h2>
<p><strong>此程序依赖的包有</strong>：</p>
<ul>
<li><strong>BeautifulSoup</strong> &#8211; <a rel="nofollow" href="http://www.crummy.com/software/BeautifulSoup/documentation.zh.html" class="broken_link">http://www.crummy.com/software/BeautifulSoup/documentation.zh.html</a></li>
<li><strong>chardet</strong> &#8211; <span class="removed_link" title="http://chardet.feedparser.org/download/">http://chardet.feedparser.org/download/</span></li>
</ul>
<h2>结语：</h2>
<p>我测试爬完第一页用了260秒+(WLAN), 56秒+(LAN)，看来无线网卡掉包的厉害呀~~~</p>
<p>写得不好，请别见笑~~~</p>
<h2>{PS}</h2>
<p>其实我还有一个多线程版本，比这个要快一点，但还是觉得不够好，想做成GUI的。<br />
最主要的原因是，设计图片共94页，每页30组, 每组按平均5张图片计算，每张图片按我爬第一页的平均SIZE: 500Kb计算，就这样也超过4G的数据，以我无线网卡的能力要下载4G估计是很痛苦的事情。<br />
所以，必须要减少分析页面的次数，并可以哪停下哪，以配合我的上班时间。</p>
<p>{OVER}</p>
<script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_python.js"></script><h3  class="related_post_title">既然来了，也许你也会想看一下：</h3><ul class="related_post"><li>2011/05/06 -- <a href="http://www.movoin.com/php-weather-class.html" title="PHP抓取天气预报">PHP抓取天气预报</a></li><li>2010/12/29 -- <a href="http://www.movoin.com/install-webpy-in-win7.html" title="Win7下配置web.py(apache+mod_wsgi+MySQLdb)">Win7下配置web.py(apache+mod_wsgi+MySQLdb)</a></li><li>2010/10/15 -- <a href="http://www.movoin.com/pygtk-treeview-display-pixbuf.html" title="PyGTK中Treeview显示Pixbuf图标">PyGTK中Treeview显示Pixbuf图标</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.movoin.com/python-devel-spider.html/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Win7下配置web.py(apache+mod_wsgi+MySQLdb)</title>
		<link>http://www.movoin.com/install-webpy-in-win7.html</link>
		<comments>http://www.movoin.com/install-webpy-in-win7.html#comments</comments>
		<pubDate>Wed, 29 Dec 2010 03:34:40 +0000</pubDate>
		<dc:creator>Allen</dc:creator>
				<category><![CDATA[程序开发]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web.py]]></category>

		<guid isPermaLink="false">http://www.movoin.com/?p=77</guid>
		<description><![CDATA[Win7下配置web.py(apache+mod_wsgi+MySQLdb) 以前在Ubuntu下配置过好几次，很简单。现在却慑于Photoshop的&#8221;淫威&#8221;，使我不得不回到Windows下工作。不过还好Win7除了开关机慢一点以外，其它都还算是不错。为此我也可以使用更多优秀软件，如：Enterprise Architect等。 言归正传，其实整个配置过程挺简单，没有多复杂，主要是找对版本和方法。 配置环境 Win7 旗舰版 32位 Python 2.7 web.py 0.3.4 Apache 2.2 MySQL 5.1 mod_wsgi py27-3.3 MySQLdb py27-1.2.3 安装Python&#8230; 下载Python有些郁闷，因为{你懂的。。。此处省略3500字。。。}，所以需要使用IE代理下载。 安装后，你需要检查一下环境变量是否已添加，我安装时不是选择所有用户，所以Path中没有Python的路径，需要我在用户配置中添加了Path。 添加用户配置后，需要注销用户再登录才可以使用Path变量。 安装Apache&#038;MySQL&#8230; 我除了需要Python环境以外，还需要PHP环境。安装也没什么特别，网上可以找到很多相关的文章，Google一下吧{PS: Google时好时坏，太杯具了！此处再次省略3500字。。。}。 安装web.py&#8230; 从web.py官网上下载0.3.4稳定版，解压后执行：python setup.py install 一般情况下不会有啥问题{PS: 我在安装时错把 writing: xxxxxxx 看成了 warnting: xxxxxxx ，还着实让我紧张了一把}。 OK，测试一下先： # filename: code.py import web urls = ( '/(.*)', 'hello' ) app = web.application(urls, globals()) [...]]]></description>
			<content:encoded><![CDATA[<p>Win7下配置web.py(apache+mod_wsgi+MySQLdb)</p>
<p>以前在Ubuntu下配置过好几次，很简单。现在却慑于Photoshop的&#8221;淫威&#8221;，使我不得不回到Windows下工作。不过还好Win7除了开关机慢一点以外，其它都还算是不错。为此我也可以使用更多优秀软件，如：Enterprise Architect等。</p>
<p>言归正传，其实整个配置过程挺简单，没有多复杂，主要是找对版本和方法。</p>
<h2>配置环境</h2>
<ol>
<li>Win7 旗舰版 32位</li>
<li>Python 2.7</li>
<li>web.py 0.3.4</li>
<li>Apache 2.2</li>
<li>MySQL 5.1</li>
<li>mod_wsgi py27-3.3</li>
<li>MySQLdb py27-1.2.3</li>
</ol>
<p><span id="more-77"></span></p>
<p></p>
<h2>安装Python&#8230;</h2>
<p>下载Python有些郁闷，因为{你懂的。。。此处省略3500字。。。}，所以需要使用IE代理下载。</p>
<p>安装后，你需要检查一下环境变量是否已添加，我安装时不是选择所有用户，所以Path中没有Python的路径，需要我在用户配置中添加了Path。</p>
<p>添加用户配置后，需要注销用户再登录才可以使用Path变量。</p>
<p></p>
<h2>安装Apache&#038;MySQL&#8230;</h2>
<p>我除了需要Python环境以外，还需要PHP环境。安装也没什么特别，网上可以找到很多相关的文章，Google一下吧{PS: Google时好时坏，太杯具了！此处再次省略3500字。。。}。</p>
<p></p>
<h2>安装web.py&#8230;</h2>
<p>从web.py官网上下载0.3.4稳定版，解压后执行：python setup.py install</p>
<p>一般情况下不会有啥问题{PS: 我在安装时错把 writing: xxxxxxx 看成了 warnting: xxxxxxx ，还着实让我紧张了一把}。</p>
<p>OK，测试一下先：</p>
<pre name="code" class="sh_python" linenum="off"># filename: code.py

import web

urls = (
    '/(.*)', 'hello'
)

app = web.application(urls, globals())

class hello:
    def GET(self, name):
        if not name:
            name = 'World'
        return 'Hello, ' + name + '!'

if __name__ == "__main__":
    app.run()
</pre>
<p>从官网上Copy的，web.py示例代码，运行：python code.py 向世界 say hello！</p>
<p></p>
<h2>安装mod_wsgi&#8230;</h2>
<ol>
<li><strong>下载 mod_wsgi</strong>: <a rel="nofollow" href="http://code.google.com/p/modwsgi/downloads/detail?name=mod_wsgi-win32-ap22py27-3.3.so" ref="nofollow">http://code.google.com/p/modwsgi/downloads/detail?name=mod_wsgi-win32-ap22py27-3.3.so</a></li>
<li>将它解压后Copy到你的Apache模块目录中，$APACHE/modules</li>
<li>修改httpd.conf文件，添加代码 LoadModule wsgi_module modules/mod_wsgi.so # 下载后的文件名是：mod_wsgi-win32-ap22py27-3.3.so 重命名为：mod_wsgi.so 即可。</li>
<li>重启你的Apache</li>
</ol>
<p></p>
<h2>使用mod_wsgi&#8230;</h2>
<blockquote><p>官网上说：mod_wsgi offers many possible ways to expose a WSGI application in Apache&#8217;s URL hierarchy, but one simple way would be to add the following to your .htaccess:</p></blockquote>
<pre name="code" class="sh_xorg" linenum="off">
&lt;Files code.py&gt;
    SetHandler wsgi-script
    Options ExecCGI FollowSymLinks
&lt;/Files&gt;
</pre>
<p>意思是说：mod_wsgi 有很多配置方法，下面的方法是最简单的，只要在你的 .htaccess 文件里添加以下代码。确实够简单的，呵呵！</p>
<p>使用 mod_wsgi 需要在你的python代码里添加几句代码才可以，拿上面的示例代码为例：</p>
<pre name="code" class="sh_python" linenum="off"># filename: code.py

import web

urls = (
    '/(.*)', 'hello'
)

app = web.application(urls, globals(), autoreload=False)

class hello:
    def GET(self, name):
        if not name:
            name = 'World'
        return 'Hello, ' + name + '!'

if __name__ == "__main__":
    app.run()

application = app.wsgifunc()
</pre>
<p><strong>创建一个虚拟主机：</strong></p>
<pre name="code" class="sh_xorg" linenum="off">
&lt;VirtualHost *:80&gt;
    ServerName your-domain.com
    ServerAlias www.your-domain.com
    DocumentRoot &quot;E:/wwwroot/python/demo/&quot;

    &lt;Directory &quot;E:/wwwroot/python/demo&quot;&gt;
        Options FollowSymLinks IncludesNOEXEC Indexes
        AllowOverride all
        Order Deny,Allow
        Allow from all
    &lt;/Directory&gt;

    ErrorLog &quot;logs/your-domain-error.log&quot;
    CustomLog &quot;logs/your-domain-access.log&quot; combined

&lt;/VirtualHost&gt;
</pre>
<p>设置本机的hosts，127.0.0.1    www.your-domain.com</p>
<p>访问你的应用：http://www.your-domain.com/code.py/</p>
<p>更多内容请移步：http://webpy.org/install/#apachemodwsgi</p>
<p></p>
<h2>安装MySQLdb(mysql_python)&#8230;</h2>
<p>作者并没有提供win(py2.7)下的.exe安装文件，我使用的是 http://www.codegood.com/archives/129，在此对作者表示感谢！</p>
<p>{PS: 我用setup.py死活装不上去}</p>
<p>OK，import MySQLdb 试下，看看 MySQLdb.__version__ 输出的是否1.2.3?</p>
<p>{OVER}</p>
<script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_python.js"></script><script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_xorg.js"></script><script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_python.js"></script><script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_xorg.js"></script><h3  class="related_post_title">既然来了，也许你也会想看一下：</h3><ul class="related_post"><li>2011/01/18 -- <a href="http://www.movoin.com/python-devel-spider.html" title="Python编写蜘蛛/爬虫">Python编写蜘蛛/爬虫</a></li><li>2010/10/15 -- <a href="http://www.movoin.com/pygtk-treeview-display-pixbuf.html" title="PyGTK中Treeview显示Pixbuf图标">PyGTK中Treeview显示Pixbuf图标</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.movoin.com/install-webpy-in-win7.html/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PyGTK中Treeview显示Pixbuf图标</title>
		<link>http://www.movoin.com/pygtk-treeview-display-pixbuf.html</link>
		<comments>http://www.movoin.com/pygtk-treeview-display-pixbuf.html#comments</comments>
		<pubDate>Fri, 15 Oct 2010 02:30:49 +0000</pubDate>
		<dc:creator>Allen</dc:creator>
				<category><![CDATA[程序开发]]></category>
		<category><![CDATA[PyGTK]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.movoin.com/?p=48</guid>
		<description><![CDATA[最近很忙，而且忙的都不是与PHP相关的工作，有的是管理方面的、还有是让我很杯具的设计和动画～～～总之，十一放完假从家里回来以后，我就陷入了这种混乱的杯具状态中。 (图为：项目管理工具) 十一放假以前就开始写一个部门内部项目管理工具，用Python 2.6 + PyGTK 2.16 + SQLite 3来写的。之所以选择用Python开发，而且还不是Web应用，是因为，一方面是想检验一下自己这么长时间来学习Python的成果；另一方面我也需要换换脑子，每天都围着Web转，确实挺烦闷的～～～ 我现在还处于初学阶段，考虑问题比较简单，只要能够实现，我就已经很高兴了～～ #!/usr/bin/env python # # [SNIPPET_NAME: File Listing] # [SNIPPET_CATEGORIES: PyGTK] # [SNIPPET_DESCRIPTION: Provide a list of files in a tree view] import os, stat, time import pygtk pygtk.require('2.0') import gtk folderxpm = [ "17 16 7 1", " c #000000", ". c #808000", "X [...]]]></description>
			<content:encoded><![CDATA[<p>最近很忙，而且忙的都不是与PHP相关的工作，有的是管理方面的、还有是让我很杯具的设计和动画～～～总之，十一放完假从家里回来以后，我就陷入了这种混乱的杯具状态中。</p>
<p><img src="http://images.homezz.com?i=aHR0cDovL2Zhcm01LnN0YXRpYy5mbGlja3IuY29tLzQxNTQvNTA4MjMwMTQ3OV8zMTA0MTZmNDRjX28ucG5n" alt=" PyGTK中Treeview显示Pixbuf图标"  title="PyGTK中Treeview显示Pixbuf图标" /><br />
(图为：项目管理工具)</p>
<p>十一放假以前就开始写一个部门内部项目管理工具，用Python 2.6 + PyGTK 2.16 + SQLite 3来写的。之所以选择用Python开发，而且还不是Web应用，是因为，一方面是想检验一下自己这么长时间来学习Python的成果；另一方面我也需要换换脑子，每天都围着Web转，确实挺烦闷的～～～<br />
<span id="more-48"></span><br />
我现在还处于初学阶段，考虑问题比较简单，只要能够实现，我就已经很高兴了～～</p>
<pre class="sh_python">#!/usr/bin/env python
#
# [SNIPPET_NAME: File Listing]
# [SNIPPET_CATEGORIES: PyGTK]
# [SNIPPET_DESCRIPTION: Provide a list of files in a tree view]

import os, stat, time
import pygtk
pygtk.require('2.0')
import gtk

folderxpm = [
    "17 16 7 1",
    "  c #000000",
    ". c #808000",
    "X c yellow",
    "o c #808080",
    "O c #c0c0c0",
    "+ c white",
    "@ c None",
    "@@@@@@@@@@@@@@@@@",
    "@@@@@@@@@@@@@@@@@",
    "@@+XXXX.@@@@@@@@@",
    "@+OOOOOO.@@@@@@@@",
    "@+OXOXOXOXOXOXO. ",
    "@+XOXOXOXOXOXOX. ",
    "@+OXOXOXOXOXOXO. ",
    "@+XOXOXOXOXOXOX. ",
    "@+OXOXOXOXOXOXO. ",
    "@+XOXOXOXOXOXOX. ",
    "@+OXOXOXOXOXOXO. ",
    "@+XOXOXOXOXOXOX. ",
    "@+OOOOOOOOOOOOO. ",
    "@                ",
    "@@@@@@@@@@@@@@@@@",
    "@@@@@@@@@@@@@@@@@"
    ]
folderpb = gtk.gdk.pixbuf_new_from_xpm_data(folderxpm)

filexpm = [
    "12 12 3 1",
    "  c #000000",
    ". c #ffff04",
    "X c #b2c0dc",
    "X        XXX",
    "X ...... XXX",
    "X ......   X",
    "X .    ... X",
    "X ........ X",
    "X .   .... X",
    "X ........ X",
    "X .     .. X",
    "X ........ X",
    "X .     .. X",
    "X ........ X",
    "X          X"
    ]
filepb = gtk.gdk.pixbuf_new_from_xpm_data(filexpm)

class FileListingCellDataExample:
    column_names = ['Name', 'Size', 'Mode', 'Last Changed']

    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return False

    def __init__(self, dname = None):
        cell_data_funcs = (None, self.file_size, self.file_mode,
                           self.file_last_changed)

        # Create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)

        self.window.set_size_request(400, 300)

        self.window.connect("delete_event", self.delete_event)

        listmodel = self.make_list(dname)

        # create the TreeView
        self.treeview = gtk.TreeView()

        # create the TreeViewColumns to display the data
        self.tvcolumn = [None] * len(self.column_names)
        cellpb = gtk.CellRendererPixbuf()
        self.tvcolumn[0] = gtk.TreeViewColumn(self.column_names[0], cellpb)
        self.tvcolumn[0].set_cell_data_func(cellpb, self.file_pixbuf)
        cell = gtk.CellRendererText()
        self.tvcolumn[0].pack_start(cell, False)
        self.tvcolumn[0].set_cell_data_func(cell, self.file_name)
        self.treeview.append_column(self.tvcolumn[0])
        for n in range(1, len(self.column_names)):
            cell = gtk.CellRendererText()
            self.tvcolumn[n] = gtk.TreeViewColumn(self.column_names[n], cell)
            if n == 1:
                cell.set_property('xalign', 1.0)
            self.tvcolumn[n].set_cell_data_func(cell, cell_data_funcs[n])
            self.treeview.append_column(self.tvcolumn[n])

        self.treeview.connect('row-activated', self.open_file)
        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.add(self.treeview)
        self.window.add(self.scrolledwindow)
        self.treeview.set_model(listmodel)

        self.window.show_all()
        return

    def make_list(self, dname=None):
        if not dname:
            self.dirname = os.path.expanduser('~')
        else:
            self.dirname = os.path.abspath(dname)
        self.window.set_title(self.dirname)
        files = [f for f in os.listdir(self.dirname) if f[0] &lt;&gt; '.']
        files.sort()
        files = ['..'] + files
        listmodel = gtk.ListStore(object)
        for f in files:
            listmodel.append([f])
        return listmodel

    def open_file(self, treeview, path, column):
        model = treeview.get_model()
        iter = model.get_iter(path)
        filename = os.path.join(self.dirname, model.get_value(iter, 0))
        filestat = os.stat(filename)
        if stat.S_ISDIR(filestat.st_mode):
            new_model = self.make_list(filename)
            treeview.set_model(new_model)
        return

    def file_pixbuf(self, column, cell, model, iter):
        filename = os.path.join(self.dirname, model.get_value(iter, 0))
        filestat = os.stat(filename)
        if stat.S_ISDIR(filestat.st_mode):
            pb = folderpb
        else:
            pb = filepb
        cell.set_property('pixbuf', pb)
        return

    def file_name(self, column, cell, model, iter):
        cell.set_property('text', model.get_value(iter, 0))
        return

    def file_size(self, column, cell, model, iter):
        filename = os.path.join(self.dirname, model.get_value(iter, 0))
        filestat = os.stat(filename)
        cell.set_property('text', filestat.st_size)
        return

    def file_mode(self, column, cell, model, iter):
        filename = os.path.join(self.dirname, model.get_value(iter, 0))
        filestat = os.stat(filename)
        cell.set_property('text', oct(stat.S_IMODE(filestat.st_mode)))
        return

    def file_last_changed(self, column, cell, model, iter):
        filename = os.path.join(self.dirname, model.get_value(iter, 0))
        filestat = os.stat(filename)
        cell.set_property('text', time.ctime(filestat.st_mtime))
        return

def main():
    gtk.main()

if __name__ == "__main__":
    flcdexample = FileListingCellDataExample()
    main()</pre>
<p>以上代码是Acire中的File Listing, 示例中使用的是xpm图片，而我并不习惯使用这种图片，于是&#8230;</p>
<pre class="sh_python">imgpath = os.path.join(homePath, 'gui/pixmaps', 'under-started.gif')
img = gtk.gdk.pixbuf_new_from_file(imgpath)</pre>
<p>OK, 这样就得到pixbuf了～～～下面就是我的测试代码&#8230;</p>
<pre class="sh_python">#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import os

try:
    import pygtk
    pygtk.require('2.0')
except:
    pass
try:
    import gtk
except:
    sys.exit()

under_started = gtk.gdk.pixbuf_new_from_file('under-started.gif')

class TreeViewPixbuf:
    column_names = [u'项目名称', u'项目类型', u'创建日期']

    def __init__(self):
        cell_data_funcs = (None, self.project_type, self.project_date)

        # Create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(u'PyGTK中TreeView显示Pixbuf图标')
        self.window.set_size_request(400, 300)
        self.window.connect("delete_event", gtk.main_quit)

        self.listmodel = self.make_list()        

        # create the TreeView
        self.treeview = gtk.TreeView()

        # create the TreeViewColumns to display the data
        self.tvcolumn = [None] * len(self.column_names)
        cellpb = gtk.CellRendererPixbuf()
        self.tvcolumn[0] = gtk.TreeViewColumn(self.column_names[0], cellpb)
        self.tvcolumn[0].set_cell_data_func(cellpb, self.project_pixbuf)
        cell = gtk.CellRendererText()
        self.tvcolumn[0].pack_start(cell, False)
        self.tvcolumn[0].set_cell_data_func(cell, self.project_name)
        self.treeview.append_column(self.tvcolumn[0])

        for n in range(1, len(self.column_names)):
            cell = gtk.CellRendererText()
            self.tvcolumn[n] = gtk.TreeViewColumn(self.column_names[n], cell)
            if n == 1:
                cell.set_property('xalign', 1.0)
            self.tvcolumn[n].set_cell_data_func(cell, cell_data_funcs[n])
            self.treeview.append_column(self.tvcolumn[n])

        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.add(self.treeview)
        self.window.add(self.scrolledwindow)

        self.treeview.set_model(self.listmodel)

        self.window.show_all()

    def make_list(self):
        listmodel = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str)
        for i in range(10):
            listmodel.append([None, 'project %d' % (i+1), 'type', '2010-10-15'])
        return listmodel

    def project_pixbuf(self, column, cell, model, iter):
        cell.set_property('pixbuf', under_started)
        return

    def project_name(self, column, cell, model, iter):
        cell.set_property('text', model.get_value(iter, 1))
        return

    def project_type(self, column, cell, model, iter):
        cell.set_property('text', model.get_value(iter, 2))
        return

    def project_date(self, column, cell, model, iter):
        cell.set_property('text', model.get_value(iter, 3))
        return

def main():
    gtk.main()

if __name__ == '__main__':
    treeview = TreeViewPixbuf()
    main()</pre>
<p><img src="http://images.homezz.com?i=aHR0cDovL2Zhcm01LnN0YXRpYy5mbGlja3IuY29tLzQxMzMvNTA4MjMwMTM1OV9hNWMxNzI4NTZjX28ucG5n" alt=" PyGTK中Treeview显示Pixbuf图标"  title="PyGTK中Treeview显示Pixbuf图标" /><br />
(图为：测试代码的运行结果)</p>
<p>学习不久，代码粗劣，还请多多见谅！</p>
<script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_python.js"></script><script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_python.js"></script><script type="text/javascript" src="/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_python.js"></script><h3  class="related_post_title">既然来了，也许你也会想看一下：</h3><ul class="related_post"><li>2011/01/18 -- <a href="http://www.movoin.com/python-devel-spider.html" title="Python编写蜘蛛/爬虫">Python编写蜘蛛/爬虫</a></li><li>2010/12/29 -- <a href="http://www.movoin.com/install-webpy-in-win7.html" title="Win7下配置web.py(apache+mod_wsgi+MySQLdb)">Win7下配置web.py(apache+mod_wsgi+MySQLdb)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.movoin.com/pygtk-treeview-display-pixbuf.html/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

