<?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>幻想曲.Net</title>
	<atom:link href="http://www.yibin001.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.yibin001.com</link>
	<description>面朝大海，春暖花开</description>
	<lastBuildDate>Sat, 13 Mar 2010 08:51:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>google appengine中的url routing</title>
		<link>http://www.yibin001.com/archives/6775</link>
		<comments>http://www.yibin001.com/archives/6775#comments</comments>
		<pubDate>Thu, 04 Mar 2010 01:17:13 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[gae]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6775</guid>
		<description><![CDATA[在做rss4py的过程中发现这样的一个问题 ，直到现在也没有找到良好的解决方案。

def main():
    webapp.template.register_template_library('filter')
    application = webapp.WSGIApplication(
                                       [
    [...]]]></description>
			<content:encoded><![CDATA[<p>在做rss4py的过程中发现这样的一个问题 ，<del datetime="2010-03-04T04:10:22+00:00">直到现在也没有找到良好的解决方案。</del></p>
<pre class="brush: python;">
def main():
    webapp.template.register_template_library('filter')
    application = webapp.WSGIApplication(
                                       [
                                        (r'/member/(?P&lt;site&gt;[0-9]+)/?', Main),
                                        (r'/member/(?P&lt;site&gt;[0-9]+)/page/(?P&lt;page&gt;[0-9]+)/?', Main),
                                        (r'/page/(?P&lt;page&gt;[0-9]*)/?', Main),
                                        ('.*',Error404),
                                       ], debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == &quot;__main__&quot;:
    main()
</pre>
<p>在这里，有三种符合匹配条件的url被交给Main controller去处理，即：</p>
<ol>
<li>/member/1                                 成员ID为1的记录</li>
<li>/member/1/page/2                成员ID为1的第2页记录</li>
<li>/page/1                                         所有成页的第1页记录</li>
</ol>
<p>Main Controller:</p>
<pre class="brush: python;">
class Main():
    def get(self,site = 0,page=1):
        self.write('site : %s' % site)
        self.write('&lt;br /&gt;page: %s' % page)
        return
</pre>
<p>当访问/member/1/时，输出：site:1 page:1<br />
访问/member/1/page/2/ 时，输出： site:1 page:2<br />
访问/page/3 时，输出：site:3 page:1<br />
可以看出，前面二个URL的区配都是正确的，但第3个是错误的，需要的输出是：site:0 page:3，很明显，3被当成参数site被传递了，<br />
如果单纯交换Main/get方法中site/page参数的顺序的话，第三个URL匹配正确，第一、二个就不正确了。</p>
<p>方案1：将URL规则做如下修改：</p>
<pre class="brush: python;">
def main():
    webapp.template.register_template_library('filter')
    application = webapp.WSGIApplication(
                                       [
                                       (r'/(?P&lt;site&gt;member/[0-9]+)/?', Main),
                                       (r'/(?P&lt;site&gt;member/[0-9]+)/(?P&lt;page&gt;page/[0-9]+)/?', Main),
                                       (r'/(?P&lt;page&gt;page/[0-9]*)/?', Main),
                                       ], debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == &quot;__main__&quot;:
    main()
</pre>
<p>修改后的URL规则中将member/page都做为参数传递到Main的get方法中，即访问/member/1/page/5时，get方法中的site参数值为member/1，page参数值为page/5，这样轻易分析一下就能得到正确的site/page值。</p>
<p>方案2：一个URL规则搞定：</p>
<p>(?:/member/(?P&lt;site&gt;[0-9]+))?(?:/page/?(?P&lt;page&gt;[0-9]+))?/?</p>
<p>这个正则太狠了</p>
<p><!-- WSA: rules for context 'adv-1' did not apply --></p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6775/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>臭蛋聚测试版发布</title>
		<link>http://www.yibin001.com/archives/6772</link>
		<comments>http://www.yibin001.com/archives/6772#comments</comments>
		<pubDate>Thu, 25 Feb 2010 03:13:15 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[gae]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6772</guid>
		<description><![CDATA[臭蛋聚是一个RSS聚合器，构建在Google App Engine上的，写的这个小应用是用来取代原有的feed.yibin001.com(和谐了)。
有段时间没写gae的小应用了，刚开始时还显得有点陌生，在此期间也遇到一些小问题，在这里一并写出来，希望对初次开发gae应用的朋友有一个帮助。

gae datastore，在gae中，所有Gql的排序字段都是需要建索引的，否则会出现经典的&#8221;NeedIndexError: no matching index found.&#8221;错误，附在错误后面的信息就是需要建立的索引，你可以复制下来，然后粘帖到index.yaml文件，并上传。上传后并不能马上使用，gae需要一个build的过程，这个时间长短要看数据量的大小，索引状态变成Serving时就意味着索引已创建成功。
Gql查询结果排序问题。排序的字段要有值，不能为None，否则结果集可能不是你所需要的。如:SELECT * FROM Feeds ORDER BY LastPubDate DESC，如果此时的LastPubDate都没有值，即使有10条数据，这条查询无法返回记录的。
对于GMT(rfc822)时间格式的解析。按rss标准，PubDate正确格式应该是Sat, 20 Feb 2010 07:04:52 +0000，直接用datetime模块解析不是很方便，可以用rfc822模块中的parsedate_tz函数进行转换。对于非标准GMT(rfc822)格式的时间，只能配合正则进行解析。

最后，臭蛋聚的地址为:http://rss4py.appspot.com/
]]></description>
			<content:encoded><![CDATA[<p><a href="http://rss4py.appspot.com/" target="_blank">臭蛋聚</a>是一个RSS聚合器，构建在Google App Engine上的，写的这个小应用是用来取代原有的feed.yibin001.com(和谐了)。</p>
<p>有段时间没写gae的小应用了，刚开始时还显得有点陌生，在此期间也遇到一些小问题，在这里一并写出来，希望对初次开发gae应用的朋友有一个帮助。</p>
<ol>
<li>gae datastore，在gae中，所有Gql的排序字段都是需要建索引的，否则会出现经典的&#8221;NeedIndexError: no matching index found.&#8221;错误，附在错误后面的信息就是需要建立的索引，你可以复制下来，然后粘帖到index.yaml文件，并上传。上传后并不能马上使用，gae需要一个build的过程，这个时间长短要看数据量的大小，索引状态变成<strong>Serving</strong>时就意味着索引已创建成功。</li>
<li>Gql查询结果排序问题。排序的字段要有值，不能为None，否则结果集可能不是你所需要的。如:SELECT * FROM Feeds ORDER BY LastPubDate DESC，如果此时的LastPubDate都没有值，即使有10条数据，这条查询无法返回记录的。</li>
<li>对于GMT(rfc822)时间格式的解析。按rss标准，PubDate正确格式应该是Sat, 20 Feb 2010 07:04:52 +0000，直接用datetime模块解析不是很方便，可以用rfc822模块中的parsedate_tz函数进行转换。对于非标准GMT(rfc822)格式的时间，只能配合正则进行解析。</li>
</ol>
<p>最后，臭蛋聚的地址为:<a href="http://rss4py.appspot.com">http://rss4py.appspot.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6772/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>album4gae及imagespider版本更新</title>
		<link>http://www.yibin001.com/archives/6763</link>
		<comments>http://www.yibin001.com/archives/6763#comments</comments>
		<pubDate>Fri, 19 Feb 2010 10:48:39 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[没有分类]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6763</guid>
		<description><![CDATA[album4gae没有做较大的调整，后台图片上传改用swfupload的批量上传，单个文件同样受gae的限制，不能超过1M。

上传成功后的预览：

前台演示：
http://album4gae.appspot.com
imagespider增加对image.google.cn的搜索支持，图片保存在程序目录/download/搜索关键字下，目录安排更为合理。

album4gae请到这里下载：
http://code.google.com/p/album4gae/downloads/list
imagespider下载：
http://www.yibin001.com/files/imagespider.rar
]]></description>
			<content:encoded><![CDATA[<p><strong>album4gae</strong>没有做较大的调整，后台图片上传改用swfupload的批量上传，单个文件同样受gae的限制，不能超过1M。</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2010/02/00002.png"><img class="alignnone size-full wp-image-6764" title="00002" src="http://www.yibin001.com/wp-content/uploads/2010/02/00002.png" alt="" width="417" height="270" /></a></p>
<p>上传成功后的预览：</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2010/02/00003.png"><img class="alignnone size-full wp-image-6765" title="00003" src="http://www.yibin001.com/wp-content/uploads/2010/02/00003.png" alt="" width="574" height="301" /></a></p>
<p>前台演示：</p>
<p><a href="http://album4gae.appspot.com" target="_blank">http://album4gae.appspot.com</a></p>
<p><strong>imagespider</strong>增加对image.google.cn的搜索支持，图片保存在程序目录/download/搜索关键字下，目录安排更为合理。</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2010/02/00004.png"><img class="alignnone size-full wp-image-6766" title="00004" src="http://www.yibin001.com/wp-content/uploads/2010/02/00004.png" alt="" width="353" height="179" /></a></p>
<p>album4gae请到这里下载：</p>
<p><a href="http://code.google.com/p/album4gae/downloads/list" target="_blank">http://code.google.com/p/album4gae/downloads/list</a></p>
<p>imagespider下载：</p>
<p><a href="http://www.yibin001.com/files/imagespider.rar" target="_blank">http://www.yibin001.com/files/imagespider.rar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6763/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>遍历Memcached服务器的KEY列表</title>
		<link>http://www.yibin001.com/archives/6744</link>
		<comments>http://www.yibin001.com/archives/6744#comments</comments>
		<pubDate>Wed, 25 Nov 2009 08:58:02 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Memcached]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6744</guid>
		<description><![CDATA[Memcached.ClientLibrary没有提供获取所有缓存KEY的方法，但有时候，我们又需要得知当前Memcached服务器上有哪些缓存key。
于是，我修改了Memcached.ClientLibrary源代码，实现了该需求。
主要通过发送stats items命令和stats cachedump x x来实现，可以先telnet上去看看

摸黑输入 stats items回车


STAT items:7:number 1
表示item7这个内存块中有一个hashkey，用stats cachedump 7 0命令即可查看

OK，开始编码吧

//更多代码
static Regex ItemReg = new Regex(@&#34;items:(\d+):number\s+(\d+)&#34;, RegexOptions.IgnoreCase);

		public List&#60;string&#62; KeyMaps()
		{
			List&#60;string&#62; list = new List&#60;string&#62;();
			List&#60;string&#62; commands = new List&#60;string&#62;();

			SockIOPool pool = SockIOPool.GetInstance(_poolName);
			ArrayList servers;

			if (pool == null)
			{
				if (log.IsErrorEnabled)
				{
					log.Error(GetLocalizedString(&#34;unable to get socket pool&#34;));
				}
				return null;
			}
		   servers = pool.Servers;

			if (servers == null &#124;&#124; servers.Count &#60;= 0)
			{
				if (log.IsErrorEnabled)
				{
					log.Error(GetLocalizedString(&#34;stats no [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sourceforge.net/projects/memcacheddotnet/" target="_blank">Memcached.ClientLibrary</a>没有提供获取所有缓存KEY的方法，但有时候，我们又需要得知当前Memcached服务器上有哪些缓存key。</p>
<p>于是，我修改了<a href="http://sourceforge.net/projects/memcacheddotnet/" target="_blank">Memcached.ClientLibrary</a>源代码，实现了该需求。</p>
<p>主要通过发送stats items命令和stats cachedump x x来实现，可以先telnet上去看看</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00068.jpg"><img class="alignnone size-full wp-image-6745" title="ScreenShot00068" src="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00068.jpg" alt="ScreenShot00068" width="499" height="143" /></a></p>
<p>摸黑输入 stats items回车</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00069.jpg"><img class="alignnone size-full wp-image-6746" title="ScreenShot00069" src="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00069.jpg" alt="ScreenShot00069" width="320" height="326" /></a></p>
<p><span id="more-6744"></span></p>
<p>STAT items:7:number 1<br />
表示item7这个内存块中有一个hashkey，用stats cachedump 7 0命令即可查看</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00070.jpg"><img class="alignnone size-full wp-image-6747" title="ScreenShot00070" src="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00070.jpg" alt="ScreenShot00070" width="380" height="104" /></a></p>
<p>OK，开始编码吧</p>
<pre class="brush: csharp;">
//更多代码
static Regex ItemReg = new Regex(@&quot;items:(\d+):number\s+(\d+)&quot;, RegexOptions.IgnoreCase);

		public List&lt;string&gt; KeyMaps()
		{
			List&lt;string&gt; list = new List&lt;string&gt;();
			List&lt;string&gt; commands = new List&lt;string&gt;();

			SockIOPool pool = SockIOPool.GetInstance(_poolName);
			ArrayList servers;

			if (pool == null)
			{
				if (log.IsErrorEnabled)
				{
					log.Error(GetLocalizedString(&quot;unable to get socket pool&quot;));
				}
				return null;
			}
		   servers = pool.Servers;

			if (servers == null || servers.Count &lt;= 0)
			{
				if (log.IsErrorEnabled)
				{
					log.Error(GetLocalizedString(&quot;stats no servers&quot;));
				}
				return null;
			}
			for (int i = 0; i &lt; servers.Count; i++)
			{

				SockIO sock = pool.GetConnection((string)servers[i]);
				if (sock == null)
				{
					if (log.IsErrorEnabled)
					{
						log.Error(GetLocalizedString(&quot;unable to connect&quot;).Replace(&quot;$$Server$$&quot;, servers[i].ToString()));
					}
					continue;
				}

				string command = &quot;stats items\r\n&quot;;

				try
				{
					sock.Write(UTF8Encoding.UTF8.GetBytes(command));
					sock.Flush();

					int lineNum = 0;
					int num = 0;
					Match match = null;
					while (true)
					{
						string line = sock.ReadLine();
						if (line == END) break;
						match = ItemReg.Match(line);
						if (match.Length&gt;0)
						{
							lineNum = Convert.ToInt32(match.Groups[1].Value);
							num = Convert.ToInt32(match.Groups[2].Value);
							command = string.Format(&quot;stats cachedump {0} 0\r\n&quot;, lineNum);
							if (commands.Contains(command) == false)
								commands.Add(command);

						}
					}

					foreach (string item in commands)
					{
						sock.Write(UTF8Encoding.UTF8.GetBytes(item));
						sock.Flush();
						while (true)
						{
							string tmpline = sock.ReadLine();
							if (tmpline == END) break;
							if (tmpline!=ERROR)
							{
								string[] array = tmpline.Split(' ');
								if (!list.Contains(array[1]))
								{
									list.Add(array[1]);
								}
							}

						}
					}

				}
				catch (IOException e)
				{
					if (log.IsErrorEnabled)
					{
						log.Error(GetLocalizedString(&quot;stats IOException&quot;), e);
					}

					try
					{
						sock.TrueClose();
					}
					catch (IOException)
					{
						if (log.IsErrorEnabled)
						{
							log.Error(GetLocalizedString(&quot;failed to close some socket&quot;).Replace(&quot;$$Socket$$&quot;, sock.ToString()));
						}
					}

					sock = null;
				}

				if (sock != null)
					sock.Close();
			}

			return list;
		}
//更多代码
</pre>
<p>只需调用mc.KeyMaps()方法即可。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6744/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>可爱的python之切片操作符(Slice)</title>
		<link>http://www.yibin001.com/archives/6740</link>
		<comments>http://www.yibin001.com/archives/6740#comments</comments>
		<pubDate>Wed, 18 Nov 2009 08:33:57 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6740</guid>
		<description><![CDATA[什么是切片？
字符串、列表、元组在python中都符合“序列”这一特征，只要符合这一特征的变量我们都可以用切片(slice)去存取它们的任意部分。我们可以把序列想像成一个队列，我可能需要前面三位、后面三位、或从第三位后的四位、或隔一个取一个等，我们用切片操作符来实现上述要求。
切片操作符在python中的原型是
[start:stop:step]
即：[开始索引:结束索引:步长值]
开始索引：同其它语言一样，从0开始。序列从左向右方向中，第一个值的索引为0,最后一个为-1
结束索引：切片操作符将取到该索引为止，不包含该索引的值。
步长值：默认是一个接着一个切取，如果为2,则表示进行隔一取一操作。步长值为正时表示从左向右取，如果为负，则表示从右向左取。步长值不能为0


假设：

    li = [1,2,3,4,5,6,7]
    print li[2]                      #输出3,因为索引为2的值为3
    print li[2:4]                 [...]]]></description>
			<content:encoded><![CDATA[<p>什么是切片？</p>
<p>字符串、列表、元组在python中都符合“序列”这一特征，只要符合这一特征的变量我们都可以用切片(slice)去存取它们的任意部分。我们可以把序列想像成一个队列，我可能需要前面三位、后面三位、或从第三位后的四位、或隔一个取一个等，我们用切片操作符来实现上述要求。</p>
<p>切片操作符在python中的原型是<br />
[start:stop:step]</p>
<p>即：[开始索引:结束索引:步长值]</p>
<p>开始索引：同其它语言一样，从0开始。序列从左向右方向中，第一个值的索引为0,最后一个为-1</p>
<p>结束索引：切片操作符将取到该索引为止，不包含该索引的值。</p>
<p>步长值：默认是一个接着一个切取，如果为2,则表示进行隔一取一操作。步长值为正时表示从左向右取，如果为负，则表示从右向左取。步长值不能为0</p>
<p><span id="more-6740"></span></p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00065.jpg"><img class="alignnone size-full wp-image-6741" title="ScreenShot00065" src="http://www.yibin001.com/wp-content/uploads/2009/11/ScreenShot00065.jpg" alt="ScreenShot00065" width="578" height="68" /></a></p>
<p>假设：</p>
<pre class="brush: plain;">
    li = [1,2,3,4,5,6,7]
    print li[2]                      #输出3,因为索引为2的值为3
    print li[2:4]                   #输出[3,4]。从索引2开始取，到索引为4的5为止(不含5)
    print li[-1]                     #输出7,反向取第一个
    print li[-1:-5:2]              #输出空列表[]，从反向第1个向反向第5个取，但步长为2,表示正向相隔二个取值。
    print li[-1:-5:-2]            #输出[7,5]
</pre>
<p>有时我们可以省略开始索引、结束索引，如：</p>
<pre class="brush: plain;">
    li = [1,2,3,4,5,6,7]
    print li[1:]           #输出[2,3,4,5,6,7]，省略终止索引，表示取起始索引之后的所有值，等效于li[1:len(li)]
    print li[:3]           #输出[1,2,3]，省略起始索引，表示从0开始取，等效于li[0:3]
    print li[:]            #输出[1,2,3,4,5,6,7]，省略起始索引、终止索引、步长值表示取全部，等效于li[0:len(li):1]
    print li[::]           #输出[1,2,3,4,5,6,7]，省略起始索引、终止索引、步长值表示取全部，等效于li[0:len(li):1]
    print li[::-1]        #输出[7,6,5,4,3,2,1]，省略起始索引、终止索引，步长值为-1，表示反向获取
</pre>
<p>所以，不要为str类没有substring方法而感到困惑，用切片操作符吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6740/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>可爱的python之语句与语法</title>
		<link>http://www.yibin001.com/archives/6735</link>
		<comments>http://www.yibin001.com/archives/6735#comments</comments>
		<pubDate>Sun, 15 Nov 2009 09:25:17 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6735</guid>
		<description><![CDATA[注释(#)：
python中的注释是以#开头的，不像c++中有/**/之类的多行注释。
继续(\)：表示继续上一行，通常情况下，一行表示一个语句，一行过长的语句可以使用\进行分解
语句块(:)：在c#/php/javascript/c++中，对于复合语句是用{}来标识，而在python中，是用：配合缩进来实现语句块，如：

if a&#62;0:
    #todo
else:
    #todo


所有的复合语句(if/for/while/)或类定义、函数定义都要用：配合缩进实现。python中的缩进不光是一种代码风格，更是一种代码标准，不同的缩进层次代表不同的语句体。
一行多条语句(;)： 我们可以在一行中书写多条语句，每一条语句用;分开，这是python允许的，但从代码可读性上考虑，尽量避免这种写法。
如：

import sys;x=y=1;

与其它语言一样，python的赋值操作符同样是用=号表示，python可以支持多元赋值

x=1
m=n=2
a,b,c,d=1,2,'python',[1,2,3] #很有趣的多元赋值
x=y=x+1
print x
print m,n
print a,b,c,d
print x,y
#output
2
2 2
1 2 python [1, 2, 3]
2 2

要注意的是：python不支持大多数语言所支持的自增(++)自减(&#8211;)运算符，也就是a++或a&#8211;在python中是错误的，只能a=a+1(a+=1)或a=a-1(a-=1)。
在python中，代码重用是通过“模块”来实现的，类似于c#中的程序集或c++中的头文件，模块是以模块名+.py组成，但要注意，模块名最好不要与系统模块同名，如定义一个xml.py就不是一个好主意。
引入一个模块用import关键字，对应的在c#中就是using，java中是import，php中是include，正确引入以后，就可以使用该模块中的方法或变量了(调用的方法可能会有所不同，会在后面说明)。
输入和输出：
输出用print语句，输入用raw_input，raw_input用来接收用户输入，接收到的数据均以字符串的形式表示。具体语法可以通过dir(&#8216;raw_input&#8217;)查看。
终止程序运行，可用sys模块的exit()方法。
一个py程序都会有一个主方法，该方法通常会命名为main()，但这不是绝对的，如何运行我当前的.py文件？
只需判断__name__这个超级变量的值即可，如果是直接运行.py文件，则__name__的值就是__main__，否则就是该.py文件的文件名。
m.py(m模块)

#coding:utf-8
import sys
import os

print __name__

if __name__=='__main__':
    print 'this is'+__name__

如果直接运行m.py文件，则输出：
__main__
this is__main__
请按任意键继续. . .
2.py

#coding:utf-8
import m

if __name__=='__main__':
    pass

此时在2.py中引用m模块，可以看到m模块中的__name__变量值为模块名m
m
请按任意键继续. . .
pass关键字表示什么也不做，在上面的代码中是不能省略的，这是语法的要求，虽然在c#中可以if(a){}，但python必须用pass关键字填充。
切片操作符[start:stop:step]，在dir(str)时，我们会发现没有熟悉的subString方法

['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff0000;"><strong>注释(#)</strong></span>：</p>
<p>python中的注释是以#开头的，不像c++中有/**/之类的多行注释。</p>
<p><span style="color: #ff0000;"><strong>继续(\)</strong></span>：表示继续上一行，通常情况下，一行表示一个语句，一行过长的语句可以使用\进行分解</p>
<p><span style="color: #ff0000;"><strong>语句块(:)</strong></span>：在c#/php/javascript/c++中，对于复合语句是用{}来标识，而在python中，是用：配合缩进来实现语句块，如：</p>
<pre class="brush: plain;">
if a&gt;0:
    #todo
else:
    #todo
</pre>
<p><span id="more-6735"></span></p>
<p>所有的复合语句(if/for/while/)或类定义、函数定义都要用：配合缩进实现。python中的缩进不光是一种代码风格，更是一种代码标准，不同的缩进层次代表不同的语句体。</p>
<p><span style="color: #ff0000;"><strong>一行多条语句(;)</strong></span>： 我们可以在一行中书写多条语句，每一条语句用;分开，这是python允许的，但从代码可读性上考虑，尽量避免这种写法。</p>
<p>如：</p>
<pre class="brush: plain;">
import sys;x=y=1;
</pre>
<p>与其它语言一样，python的赋值操作符同样是用=号表示，python可以支持多元赋值</p>
<pre class="brush: plain;">
x=1
m=n=2
a,b,c,d=1,2,'python',[1,2,3] #很有趣的多元赋值
x=y=x+1
print x
print m,n
print a,b,c,d
print x,y
#output
2
2 2
1 2 python [1, 2, 3]
2 2
</pre>
<p>要注意的是：python不支持大多数语言所支持的自增(++)自减(&#8211;)运算符，也就是a++或a&#8211;在python中是错误的，只能a=a+1(a+=1)或a=a-1(a-=1)。</p>
<p>在python中，代码重用是通过“模块”来实现的，类似于c#中的程序集或c++中的头文件，模块是以模块名+.py组成，但要注意，模块名最好不要与系统模块同名，如定义一个xml.py就不是一个好主意。</p>
<p>引入一个模块用import关键字，对应的在c#中就是using，java中是import，php中是include，正确引入以后，就可以使用该模块中的方法或变量了(调用的方法可能会有所不同，会在后面说明)。</p>
<p>输入和输出：</p>
<p>输出用print语句，输入用raw_input，raw_input用来接收用户输入，接收到的数据均以字符串的形式表示。具体语法可以通过dir(&#8216;raw_input&#8217;)查看。<br />
终止程序运行，可用sys模块的exit()方法。</p>
<p>一个py程序都会有一个主方法，该方法通常会命名为main()，但这不是绝对的，如何运行我当前的.py文件？</p>
<p>只需判断__name__这个超级变量的值即可，如果是直接运行.py文件，则__name__的值就是__main__，否则就是该.py文件的文件名。</p>
<p>m.py(m模块)</p>
<pre class="brush: python;">
#coding:utf-8
import sys
import os

print __name__

if __name__=='__main__':
    print 'this is'+__name__
</pre>
<blockquote><p>如果直接运行m.py文件，则输出：<br />
__main__<br />
this is__main__<br />
请按任意键继续. . .</p></blockquote>
<p>2.py</p>
<pre class="brush: python;">
#coding:utf-8
import m

if __name__=='__main__':
    pass
</pre>
<p>此时在2.py中引用m模块，可以看到m模块中的__name__变量值为模块名m</p>
<blockquote><p>m<br />
请按任意键继续. . .</p></blockquote>
<p>pass关键字表示什么也不做，在上面的代码中是不能省略的，这是语法的要求，虽然在c#中可以if(a){}，但python必须用pass关键字填充。</p>
<p>切片操作符[start:stop:step]，在dir(str)时，我们会发现没有熟悉的subString方法</p>
<pre class="brush: plain;">
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__g
t__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__
', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '
__rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode',
'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdi
git', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lst
rip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit'
, 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', '
translate', 'upper', 'zfill']
</pre>
<p>那我们如何获取指定的字符串的一部分？此时，切片操作符就派上用场了。</p>
<pre class="brush: plain;">
a='abcdefg'
print a[0:3] #abc
print a[:3]  #abc
print a[0::2]  #aceg
print a[::-1]   #gfedcba
print a[2:-3]  #cd
</pre>
<p>切片操作符同样适用于列表与元组，功能一样。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6735/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>可爱的python之快速入门</title>
		<link>http://www.yibin001.com/archives/6728</link>
		<comments>http://www.yibin001.com/archives/6728#comments</comments>
		<pubDate>Sat, 14 Nov 2009 10:49:05 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6728</guid>
		<description><![CDATA[python所支持的数据类型：
整型、长整型、布尔型、浮点型、复数、字符串、列表(list)、元组(Tuple)、字典(Dict)、object
python能支持理论意义上的长整型，如C#中的长整型是Int64，即最大值为2的64次方，而python中的长整型只与机器的虚拟内存大小有关，你完全不用考虑溢出这样的异常。
python是一种动态语言，虽然在定义变量时无需定义变量的类型，但并不意味着在运行的过程中，系统会自动更改变量的类型，所以，python是一种强类型的动态语言，它与asp/javascript/php完全不一样，比如：

&#62;&#62;&#62; a=123
&#62;&#62;&#62; print 'input '+ a
Traceback (most recent call last):
  File &#34;&#60;stdin&#62;&#34;, line 1, in &#60;module&#62;
TypeError: cannot concatenate 'str' and 'int' objects
&#62;&#62;&#62;


此时出现了一个异常“无法将字符串类型与数字类型的数据做连接操作”，而这样的语法在php/asp中是完全可行的。
bool型在python中用True/False来表示，当然，空字符串、0、空元组、空列表、空字典都会认为一个False值。
字符串是位于成对的单引、双引、三单引、三双引之间的字符。
列表类似于c#中的ArrayList，通过下标来访问。
元组是一个只读的列表。
字典类似于c#中的hashtable，它的键必须是可被hash的。
列表的定义方法:

&#62;&#62;&#62; li = [1,2,3,4,5]
&#62;&#62;&#62; li_1 = []
&#62;&#62;&#62; li_2 = range(10)
&#62;&#62;&#62; li
[1, 2, 3, 4, 5]
&#62;&#62;&#62; li_1
[]
&#62;&#62;&#62; li_2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

元组的定义与列表类似，只是把[]换成了()，但要注意：如果元组中只有一个元素，也要在该元素的后面加上,号

&#62;&#62;&#62; tu = (1,2,3)
&#62;&#62;&#62; tu_2 = (2)  [...]]]></description>
			<content:encoded><![CDATA[<p>python所支持的数据类型：<br />
整型、长整型、布尔型、浮点型、复数、字符串、列表(list)、元组(Tuple)、字典(Dict)、object</p>
<p>python能支持理论意义上的长整型，如C#中的长整型是Int64，即最大值为2的64次方，而python中的长整型只与机器的虚拟内存大小有关，你完全不用考虑溢出这样的异常。</p>
<p>python是一种动态语言，虽然在定义变量时无需定义变量的类型，但<span style="color: #ff0000;">并不意味着在运行的过程中，系统会自动更改变量的类型</span>，所以，python是一种<span style="color: #ff0000;">强类型的动态语言</span>，它与asp/javascript/php完全不一样，比如：</p>
<pre class="brush: plain;">
&gt;&gt;&gt; a=123
&gt;&gt;&gt; print 'input '+ a
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
TypeError: cannot concatenate 'str' and 'int' objects
&gt;&gt;&gt;
</pre>
<p><span id="more-6728"></span></p>
<p>此时出现了一个异常“无法将字符串类型与数字类型的数据做连接操作”，而这样的语法在php/asp中是完全可行的。</p>
<p>bool型在python中用True/False来表示，当然，空字符串、0、空元组、空列表、空字典都会认为一个False值。</p>
<p>字符串是位于成对的单引、双引、三单引、三双引之间的字符。</p>
<p>列表类似于c#中的ArrayList，通过下标来访问。</p>
<p>元组是一个只读的列表。</p>
<p>字典类似于c#中的hashtable，它的键必须是可被hash的。</p>
<p>列表的定义方法:</p>
<pre class="brush: plain;">
&gt;&gt;&gt; li = [1,2,3,4,5]
&gt;&gt;&gt; li_1 = []
&gt;&gt;&gt; li_2 = range(10)
&gt;&gt;&gt; li
[1, 2, 3, 4, 5]
&gt;&gt;&gt; li_1
[]
&gt;&gt;&gt; li_2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
</pre>
<p>元组的定义与列表类似，只是把[]换成了()，但要注意：如果元组中只有一个元素，也要在该元素的后面加上,号</p>
<pre class="brush: plain;">
&gt;&gt;&gt; tu = (1,2,3)
&gt;&gt;&gt; tu_2 = (2)       #这里会认为tu_2是一个int类型
&gt;&gt;&gt; type(tu)
&lt;type 'tuple'&gt;
&gt;&gt;&gt; type(tu_2)
&lt;type 'int'&gt;
&gt;&gt;&gt; tu_2 = (2,)
&gt;&gt;&gt; type(tu_2)
&lt;type 'tuple'&gt;
</pre>
<p>字典用大括号标识，多个元素用,分开，这点跟Json一样</p>
<pre class="brush: plain;">
&gt;&gt;&gt; dic = {'name':'yibin','email':'yibin.net@gmail.com'}
&gt;&gt;&gt; type(dic)
&lt;type 'dict'&gt;
&gt;&gt;&gt; dic
{'name': 'yibin', 'email': 'yibin.net@gmail.com'}
</pre>
<p>可以用keys()方法得到该字典的键，用values()方法得到值，用items()方法得到以键－值为一组的列表</p>
<pre class="brush: plain;">
['name', 'email']
['yibin', 'yibin.net@gmail.com']
[('name', 'yibin'), ('email', 'yibin.net@gmail.com')]
</pre>
<p>可以把多个列表相加，如：</p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;"> </span></p>
<pre class="brush: plain;">
    a = [1,2,3,4]
    b = [5,6,7,8]
    c = a+b
    print a
    print b
    print c
    a.append(b)
    c.extend(b)
    print a
    print c
运行结果：
[1, 2, 3, 4]
[5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, [5, 6, 7, 8]]
[1, 2, 3, 4, 5, 6, 7, 8, 5, 6, 7, 8]
请按任意键继续. . .
</pre>
<p>注意看append与extend方法的区别。</p>
<p>想得知list/tuple/str/dict有哪些可用的方法和属性，可以用dir函数；可以用help()函数获取相应的帮助</p>
<pre class="brush: plain;">
&gt;&gt;&gt; dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delsli
ce__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__gets
lice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '
__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__r
educe_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__
', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'p
op', 'remove', 'reverse', 'sort']
&gt;&gt;&gt; dir(tuple)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__g
t__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul_
_', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__',
'__setattr__', '__str__']
&gt;&gt;&gt;
</pre>
<p>不要惊讶于dir(tuple)为什么没有方法可用，因为tuple是只读的。</p>
<p>获取关于list的extend方法的帮助：</p>
<pre class="brush: plain;">
&gt;&gt;&gt; help(list.extend)
Help on method_descriptor:

extend(...)
    L.extend(iterable) -- extend list by appending elements from the iterable
&gt;&gt;&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6728/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>可爱的python之hello,world!</title>
		<link>http://www.yibin001.com/archives/6710</link>
		<comments>http://www.yibin001.com/archives/6710#comments</comments>
		<pubDate>Fri, 13 Nov 2009 13:57:56 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6710</guid>
		<description><![CDATA[python3.0已推出，但据说很多库都不能用了，建议使用2.6版本，我目前使用的是2.5版，与2.6版差距不大。
注意：2.6版本开始，print需要加上括号，否则会提示语法错误。
安装python运行环境：

下载for windows的安装包，http://www.python.org/，不过，正式对外的下载地址被和谐了，请移步到这里下载：http://www.python.org/ftp/python/
运行下载的.msi文件执行安装程序，默认会安装在系统盘符:/python25目录下，当然你可以更改该目录，但建议使用默认值，安装完成后会自动注册环境变量

运行cmd，执行python：

D:\&#62;python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win
32
Type &#34;help&#34;, &#34;copyright&#34;, &#34;credits&#34; or &#34;license&#34; for more information.
&#62;&#62;&#62;

表示安装成功，&#62;&#62;&#62;为python默认的提示符。
首先来一个经典的hello,world

&#62;&#62;&#62; print 'hello world'
hello world

在此，有必要先认识一些系统内置的非常有用的一些函数
dir()函数用来显示一个类的所有属性和方法，如:

&#62;&#62;&#62; dir('this is a string')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__g
t__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__
', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', [...]]]></description>
			<content:encoded><![CDATA[<p>python3.0已推出，但据说很多库都不能用了，建议使用2.6版本，我目前使用的是2.5版，与2.6版差距不大。</p>
<p><span style="text-decoration: underline;"><span style="color: #ff0000;">注意：2.6版本开始，print需要加上括号，否则会提示语法错误。</span></span></p>
<p>安装python运行环境：</p>
<ol>
<li>下载for windows的安装包，http://www.python.org/，不过，正式对外的下载地址被和谐了，请移步到这里下载：<a href="http://www.python.org/ftp/python/" target="_blank">http://www.python.org/ftp/python/</a></li>
<li>运行下载的.msi文件执行安装程序，默认会安装在系统盘符:/python25目录下，当然你可以更改该目录，但建议使用默认值，安装完成后会自动注册环境变量</li>
</ol>
<p>运行cmd，执行python：</p>
<pre class="brush: plain;">
D:\&gt;python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win
32
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&gt;&gt;&gt;
</pre>
<p>表示安装成功，&gt;&gt;&gt;为python默认的提示符。</p>
<p>首先来一个经典的hello,world</p>
<pre class="brush: plain;">
&gt;&gt;&gt; print 'hello world'
hello world
</pre>
<p>在此，有必要先认识一些系统内置的非常有用的一些函数</p>
<p><span style="color: #0000ff;"><strong>dir</strong></span><span style="color: #0000ff;"><strong>()</strong></span>函数用来显示一个类的所有属性和方法，如:</p>
<pre class="brush: plain;">
&gt;&gt;&gt; dir('this is a string')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__g
t__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__
', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '
__rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode',
'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdi
git', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lst
rip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit'
, 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', '
translate', 'upper', 'zfill']
&gt;&gt;&gt;
</pre>
<p>基本上，以__(双划线)开头的方法，你是不能直接通过类去调用（但可以通过其它的途径去调用），它们相当于php类中的&#8221;魔术方法&#8221;。</p>
<p><span style="color: #0000ff;"><strong>type()</strong></span>函数用来显示当前变量的类型，如：</p>
<pre class="brush: plain;">
&gt;&gt;&gt; m=1L
&gt;&gt;&gt; n=1
&gt;&gt;&gt; i=1.3
&gt;&gt;&gt; a='123'
&gt;&gt;&gt; b=range(10)
&gt;&gt;&gt; type(m)
&lt;type 'long'&gt;
&gt;&gt;&gt; type(n)
&lt;type 'int'&gt;
&gt;&gt;&gt; type(i)
&lt;type 'float'&gt;
&gt;&gt;&gt; type(a)
&lt;type 'str'&gt;
&gt;&gt;&gt; type(b)
&lt;type 'list'&gt;
&gt;&gt;&gt; type(type(b))
&lt;type 'type'&gt;
</pre>
<p><span style="color: #0000ff;"><strong>id()</strong></span>函数用来显示指定变量的内存地址</p>
<pre class="brush: plain;">
&gt;&gt;&gt; a=b=123
&gt;&gt;&gt; m=n='123'
&gt;&gt;&gt; id(a),id(b)
(3178240, 3178240)
&gt;&gt;&gt; id(m),id(n)
(5817024, 5817024)
&gt;&gt;&gt; m='1'
&gt;&gt;&gt; id(m)
5792000
</pre>
<p><span style="color: #0000ff;"><strong>help()</strong></span>顾名思义是用来查看帮助的</p>
<pre class="brush: plain;">
&gt;&gt;&gt; help(str.find)
Help on method_descriptor:

find(...)
 S.find(sub [,start [,end]]) -&gt; int

 Return the lowest index in S where substring sub is found,
 such that sub is contained within s[start,end].  Optional
 arguments start and end are interpreted as in slice notation.

 Return -1 on failure.
</pre>
<p>另外，python的语句块是用缩进来标识的，不像c/c++/java/c#那样用{}来匹分，初次接触可能会不习惯，但时间长了，你会喜欢上这样的风格，因为它会让你感觉看所有的python代码都是一样的，不会出现参差不齐的&#8221;括号&#8221;风格。</p>
<p>开始我们的python之旅吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6710/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Discuz发帖器的实现</title>
		<link>http://www.yibin001.com/archives/6697</link>
		<comments>http://www.yibin001.com/archives/6697#comments</comments>
		<pubDate>Wed, 11 Nov 2009 11:47:19 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[discuz]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6697</guid>
		<description><![CDATA[首先要清楚discuz论坛发帖的流程，简单地说就是以下流程：
进入登录页 -&#62;登录 -&#62; 进入版面 -&#62;发帖
登录和发帖时要获取到页面的formhash值，否则会失败，如果启用了验证码，还得去分析验证码，这就比较复杂了。这里只用python来描述这一系列过程，涉及到验证码还请大家自行去实现。



#!/usr/bin/env python
#coding=utf-8
from urllib import urlencode
import cookielib, urllib2,urllib
import os,sys
import urllib2,cookielib,urllib,httplib,re

import getpass
import time

from Queue import Queue
import threading

class Discuz:
    def __init__(self,uid,pwd,debug = False,**param):
        self.username = uid
        self.password = pwd
        self.para [...]]]></description>
			<content:encoded><![CDATA[<p>首先要清楚discuz论坛发帖的流程，简单地说就是以下流程：</p>
<p>进入登录页 -&gt;登录 -&gt; 进入版面 -&gt;发帖</p>
<p>登录和发帖时要获取到页面的formhash值，否则会失败，如果启用了验证码，还得去分析验证码，这就比较复杂了。这里只用python来描述这一系列过程，涉及到验证码还请大家自行去实现。</p>
<p><span id="more-6697"></span></p>
<pre class="brush: python;">

#!/usr/bin/env python
#coding=utf-8
from urllib import urlencode
import cookielib, urllib2,urllib
import os,sys
import urllib2,cookielib,urllib,httplib,re

import getpass
import time

from Queue import Queue
import threading

class Discuz:
    def __init__(self,uid,pwd,debug = False,**param):
        self.username = uid
        self.password = pwd
        self.para = param

        #self.timelimit = timelimit
        self.regex = {
            'loginreg':'&lt;input\s*type=&quot;hidden&quot;\s*name=&quot;formhash&quot;\s*value=&quot;([\w\W]+?)&quot;\s*\/&gt;',
            'postreg':'&lt;input\s*type=&quot;hidden&quot;\s*name=&quot;formhash&quot;\s*id=&quot;formhash&quot;\s*value=&quot;([\w\W]+?)&quot;\s*\/&gt;'
        }
        self.opener = None
        self.request = None
        self.islogin = False
        self.donecount = 0
        self.__login()
        self.threadcount = 10
    def __login(self):
        try:
            loginPage = urllib2.urlopen(self.para['loginurl']).read()
            formhash = re.search(self.regex['loginreg'],loginPage)
            formhash = formhash.group(1)
            print 'start login......'
            cookiejar = cookielib.CookieJar()
            self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
            values = {
                     'formhash':formhash,
                     'username':self.username,
                     'password':self.password,
                     'loginsubmit':'true'
                    }
            data = urllib.urlencode(values)
            self.request = urllib2.Request(self.para['loginsubmiturl'], data)
            rq = self.opener.open(self.request)

            print 'login success......'
            self.islogin = True
        except Exception ,e:
            print e
    def Post(self,subject,wysiwyg,content):
        threads = []
        for i in range(self.threadcount):
            t = threading.Thread(
                target=self.__postTopic,
                kwargs={'_subject':subject,'_wysiwyg':wysiwyg,'_body':content}
            )
            threads.append(t)
        for i in range(self.threadcount):
            threads[i].start()

        for i in range(self.threadcount):
            threads[i].join()
        print 'done'
    def __postTopic(self,**para):
        if not self.islogin:
            print 'please login......'
            return

        while True:
            try:
                self.request = urllib2.Request(self.para['posturl'])
                rq = self.opener.open(self.request)
                data = rq.read()

                formhash = re.search(self.regex['postreg'],data)
                formhash =  formhash.group(1)

                postdata = {
                    'addtags':'+可用标签',
                    'checkbox':'0',
                    'formhash':formhash,
                    'iconid':'',
                    'message':para['_body'],
                    'subject':para['_subject'],
                    'tags':'',
                    'updateswfattach' : '0',
                    'wysiwyg' : para['_wysiwyg']
                }
                self.request = urllib2.Request(self.para['postsubmiturl'],urllib.urlencode(postdata))
                self.opener.open(self.request)
                self.donecount+=1
                print '%d done.....' % self.donecount
            except Exception,e:
                print e
            time.sleep(2)

if __name__=='__main__':
    name = raw_input('username:')
    password = getpass.getpass('password:')
    dz = Discuz(name,password,
    loginurl='http://xxx/logging.php?action=login',
    loginsubmiturl='http://xxx/logging.php?action=login&amp;loginsubmit=yes',
    posturl='http://xxx/post.php?action=newthread&amp;fid=5',
    postsubmiturl='http://xxx/post.php?&amp;action=newthread&amp;fid=5&amp;extra=&amp;topicsubmit=yes')
    content='''这是帖子内容'''
    dz.Post('这是帖子标题','1',content)
</pre>
<p>Discuz类中只有一个公开方法<br />
def Post(self,subject,wysiwyg,content)<br />
三个参数，分别是帖子标题、是否是可视化编辑、帖子内容。<br />
类实例化时会进行登录操作，并同时记录下cookie以备用，Post方法中会启用多个线程执行私有方法__postTopic(self,**para)进行真正的发帖操作。<br />
所以，基本上Discuz生成的formhash就是一个鸡肋 -_-</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6697/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>百度图片抓取工具</title>
		<link>http://www.yibin001.com/archives/6682</link>
		<comments>http://www.yibin001.com/archives/6682#comments</comments>
		<pubDate>Sun, 01 Nov 2009 09:17:14 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.yibin001.com/?p=6682</guid>
		<description><![CDATA[有时我们需要从baidu上找一些图片，比如某一个美女或某一个帅哥，一张一张下载太麻烦，于是产生了下面这个工具
运行截图：


分析每一页的图片地址：

启动多个线程同时下载：

下载完成：

工具会在当前运行目录生成一个download目录用来存放图片，请确保程序文件不在含有中文字符的路径中。
运行压缩包中的main.exe即可。
http://demo.yibin001.com/baiduimg_spider.zip
ps.在西塘逛了一天，好累，谢谢西厢阁客栈的沈姐，谢谢她的接送。相关影像：
http://yibinalbum.appspot.com/album/5001/
]]></description>
			<content:encoded><![CDATA[<p>有时我们需要从baidu上找一些图片，比如某一个美女或某一个帅哥，一张一张下载太麻烦，于是产生了下面这个工具</p>
<p>运行截图：</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/0000002.png"><img class="alignnone size-full wp-image-6684" title="0000002" src="http://www.yibin001.com/wp-content/uploads/2009/11/0000002.png" alt="0000002" width="413" height="126" /></a></p>
<p><span id="more-6682"></span></p>
<p>分析每一页的图片地址：</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/0000003.png"><img class="alignnone size-full wp-image-6685" title="0000003" src="http://www.yibin001.com/wp-content/uploads/2009/11/0000003.png" alt="0000003" width="646" height="173" /></a></p>
<p>启动多个线程同时下载：</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/0000004.png"><img class="alignnone size-full wp-image-6686" title="0000004" src="http://www.yibin001.com/wp-content/uploads/2009/11/0000004.png" alt="0000004" width="519" height="204" /></a></p>
<p>下载完成：</p>
<p><a href="http://www.yibin001.com/wp-content/uploads/2009/11/0000005.png"><img class="alignnone size-full wp-image-6687" title="0000005" src="http://www.yibin001.com/wp-content/uploads/2009/11/0000005.png" alt="0000005" width="560" height="401" /></a></p>
<p>工具会在当前运行目录生成一个download目录用来存放图片，请确保程序文件不在含有中文字符的路径中。</p>
<p>运行压缩包中的main.exe即可。</p>
<p><a href="http://demo.yibin001.com/baiduimg_spider.zip">http://demo.yibin001.com/baiduimg_spider.zip</a></p>
<p>ps.在西塘逛了一天，好累，谢谢西厢阁客栈的沈姐，谢谢她的接送。相关影像：</p>
<p><a href="http://yibinalbum.appspot.com/album/5001/" target="_blank">http://yibinalbum.appspot.com/album/5001/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.yibin001.com/archives/6682/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
