Gary's BLOG
我关注各种开源项目,Python, Zope, Plone, Twisted, Django... 我使用Linux, Mac OSX.
2009-05-25
DIV垂直居中对齐
<style>
#image-blip {
width: 300px;
height: 300px;
background-color: #aaaaaa;
border: solid 1px #222222;
vertical-align: middle;
}
#image-blip * {
vertical-align: middle;
}
*html #image-blip span {
height: 100%;
display: inline-block;
}
</style>
<div id="image-blip">
<span></span>
<a href="#" id="blip">
<img src="/test.jpg" />
</a>
</div>
2009-05-20
Bash Shell 快捷键
Ctrl + a - 跳到行首 Ctrl + b - 左移一个字符 Ctrl + c - 终端进程 Ctrl + d - 从光标处向右删除 Ctrl + e - 跳到行尾 Ctrl + f - 右移一个字符 Ctrl + k - 从光标处删除到行尾 Ctrl + l - 清屏,类似 clear 命令 Ctrl + r - 查找历史命令 Ctrl + R - Search the history backwards with multi occurrence Ctrl + u - Delete backward from cursor // 密码输入错误的时候比较有用 Ctrl + xx - Move between EOL and current cursor position Ctrl + x @ - Show possible hostname completions Ctrl + z - Suspend/ Stop the command 补充: Ctrl + h - 删除当前字符 Ctrl + w - 删除最后输入的单词
2008-11-04
Convert video by mencoder
http://forum.ubuntu.org.cn/viewtopic.php?t=26339
2008-10-19
转载:The Easy Way to Extract Useful Text from Arbitrary HTML(从HTML文件中抽取正文的简单方案)
译者导读:这篇文章主要介绍了从不同类型的HTML文件中抽取出真正有用的正文内容的一种有广泛适应性的方法。其功能类似于CSDN近期推出的“剪影”,能够去除页眉、页脚和侧边栏的无关内容,非常实用。其方法简单有效而又出乎意料,看完后难免大呼原来还可以这样!行文简明易懂,虽然应用了人工神经网络这样的算法,但因为FANN良好的封装性,并不要求读者需要懂得ANN。全文示例以Python代码写成,可读性更佳,具有科普气息,值得一读。
作者:alexjc
译者:恋花蝶(http://blog.csdn.net/lanphaday)
原文地址:http://ai-depot.com/articles/the-easy-way-to-extract-useful-text-from-arbitrary-html/
转载地址:http://blog.csdn.net/lanphaday/archive/2007/08/13/1741185.aspx
正文:
-----------------------------------------------------------------------------
You’ve finally got your hands on the diverse collection of HTML documents you needed. But the content you’re interested in is hidden amidst adverts, layout tables or formatting markup, and other various links. Even worse, there’s visible text in the menus, headers and footers that you want to filter out. If you don’t want to write a complex scraping program for each type of HTML file, there is a solution.
每个人手中都可能有一大堆讨论不同话题的HTML文档。但你真正感兴趣的内容可能隐藏于广告、布局表格或格式标记以及无数链接当中。甚至更糟的是,你希望那些来自菜单、页眉和页脚的文本能够被过滤掉。如果你不想为每种类型的HTML文件分别编写复杂的抽取程序的话,我这里有一个解决方案。
This article shows you how to write a relatively simple script to extract text paragraphs from large chunks of HTML code, without knowing its structure or the tags used. It works on news articles and blogs pages with worthwhile text content, among others…
本文讲述如何编写与从大量HTML代码中获取正文内容的简单脚本,这一方法无需知道HTML文件的结构和使用的标签。它能够工作于含有文本内容的所有新闻文章和博客页面……
Do you want to find out how statistics and machine learning can save you time and effort mining text?
你想知道统计学和机器学习在挖掘文本方面能够让你省时省力的原因吗?
The concept is rather simple: use information about the density of text vs. HTML code to work out if a line of text is worth outputting. (This isn’t a novel idea, but it works!) The basic process works as follows:
答案极其简单:使用文本和HTML代码的密度来决定一行文件是否应该输出。(这听起来有点离奇,但它的确有用!)基本的处理工作如下:
Parse the HTML code and keep track of the number of bytes processed.
一、解析HTML代码并记下处理的字节数。
Store the text output on a per-line, or per-paragraph basis.
二、以行或段的形式保存解析输出的文本。
Associate with each text line the number of bytes of HTML required to describe it.
三、统计每一行文本相应的HTML代码的字节数
Compute the text density of each line by calculating the ratio of text to bytes.
四、通过计算文本相对于字节数的比率来获取文本密度
Then decide if the line is part of the content by using a neural network.
五、最后用神经网络来决定这一行是不是正文的一部分。
You can get pretty good results just by checking if the line’s density is above a fixed threshold (or the average), but the system makes fewer mistakes if you use machine learning — not to mention that it’s easier to implement!
仅仅通过判断行密度是否高于一个固定的阈值(或者就使用平均值)你就可以获得非常好的结果。但你也可以使用机器学习(这易于实现,简直不值一提)来减少这个系统出现的错误。
Let’s take it from the top…
现在让我从头开始……
Converting the HTML to Text
转换HTML为文本
What you need is the core of a text-mode browser, which is already setup to read files with HTML markup and display raw text. By reusing existing code, you won’t have to spend too much time handling invalid XML documents, which are very common — as you’ll realise quickly.
你需要一个文本模式浏览器的核心,它应该已经内建了读取HTML文件和显示原始文本功能。通过重用已有代码,你并不需要把很多时间花在处理无效的XML文件上。
As a quick example, we’ll be using Python along with a few built-in modules: htmllib for the parsing and formatter for outputting formatted text. This is what the top-level function looks like:
我们将使用Python来完成这个例子,它的htmllib模块可用以解析HTML文件,formatter模块可用以输出格式化的文本。嗯,实现的顶层函数如下:
def extract_text(html):
# Derive from formatter.AbstractWriter to store paragraphs.
writer = LineWriter()
# Default formatter sends commands to our writer.
formatter = AbstractFormatter(writer)
# Derive from htmllib.HTMLParser to track parsed bytes.
parser = TrackingParser(writer, formatter)
# Give the parser the raw HTML data.
parser.feed(html)
parser.close()
# Filter the paragraphs stored and output them.
return writer.output()
The TrackingParser itself overrides the callback functions for parsing start and end tags, as they are given the current parse index in the buffer. You don’t have access to that normally, unless you start diving into frames in the call stack — which isn’t the best approach! Here’s what the class looks like:
TrackingParser覆盖了解析标签开始和结束时调用的回调函数,用以给缓冲对象传递当前解析的索引。通常你不得不这样,除非你使用不被推荐的方法——深入调用堆栈去获取执行帧。这个类看起来是这样的:
class TrackingParser(htmllib.HTMLParser):
"""Try to keep accurate pointer of parsing location."""
def __init__(self, writer, *args):
htmllib.HTMLParser.__init__(self, *args)
self.writer = writer
def parse_starttag(self, i):
index = htmllib.HTMLParser.parse_starttag(self, i)
self.writer.index = index
return index
def parse_endtag(self, i):
self.writer.index = i
return htmllib.HTMLParser.parse_endtag(self, i)
The LineWriter class does the bulk of the work when called by the default formatter. If you have any improvements or changes to make, most likely they’ll go here. This is where we’ll put our machine learning code in later. But you can keep the implementation rather simple and still get good results. Here’s the simplest possible code:
LinWriter的大部分工作都通过调用formatter来完成。如果你要改进或者修改程序,大部分时候其实就是在修改它。我们将在后面讲述怎么为它加上机器学习代码。但你也可以保持它的简单实现,仍然可以得到一个好结果。具体的代码如下:
class Paragraph:
def __init__(self):
self.text = ''
self.bytes = 0
self.density = 0.0
class LineWriter(formatter.AbstractWriter):
def __init__(self, *args):
self.last_index = 0
self.lines = [Paragraph()]
formatter.AbstractWriter.__init__(self)
def send_flowing_data(self, data):
# Work out the length of this text chunk.
t = len(data)
# We've parsed more text, so increment index.
self.index += t
# Calculate the number of bytes since last time.
b = self.index - self.last_index
self.last_index = self.index
# Accumulate this information in current line.
l = self.lines[-1]
l.text += data
l.bytes += b
def send_paragraph(self, blankline):
"""Create a new paragraph if necessary."""
if self.lines[-1].text == '':
return
self.lines[-1].text += 'n' * (blankline+1)
self.lines[-1].bytes += 2 * (blankline+1)
self.lines.append(Writer.Paragraph())
def send_literal_data(self, data):
self.send_flowing_data(data)
def send_line_break(self):
self.send_paragraph(0)
This code doesn’t do any outputting yet, it just gathers the data. We now have a bunch of paragraphs in an array, we know their length, and we know roughly how many bytes of HTML were necessary to create them. Let’s see what emerge from our statistics.
这里代码还没有做输出部分,它只是聚合数据。现在我们有一系列的文字段(用数组保存),以及它们的长度和生成它们所需要的HTML的大概字节数。现在让我们来看看统计学带来了什么。
Examining the Data
数据分析
Luckily, there are some patterns in the data. In the raw output below, you’ll notice there are definite spikes in the number of HTML bytes required to encode lines of text, notably around the title, both sidebars, headers and footers.
幸运的是,数据里总是存在一些模式。从下面的原始输出你可以发现有些文本需要大量的HTML来编码,特别是标题、侧边栏、页眉和页脚。
While the number of HTML bytes spikes in places, it remains below average for quite a few lines. On these lines, the text output is rather high. Calculating the density of text to HTML bytes gives us a better understanding of this relationship.
虽然HTML字节数的峰值多次出现,但大部分仍然低于平均值;我们也可以看到在大部分低HTML字节数的字段中,文本输出却相当高。通过计算文本与HTML字节数的比率(即密度)可以让我们更容易明白它们之间的关系:
The patterns are more obvious in this density value, so it gives us something concrete to work with.
密度值图更加清晰地表达了正文的密度更高,这是我们的工作的事实依据。
Filtering the Lines
过滤文本行
The simplest way we can filter lines now is by comparing the density to a fixed threshold, such as 50% or the average density. Finishing the LineWriter class:
过滤文本行的最简单方法是通过与一个阈值(如50%或者平均值)比较密度值。下面来完成LineWriter类:
def compute_density(self):
"""Calculate the density for each line, and the average."""
total = 0.0
for l in self.lines:
l.density = len(l.text) / float(l.bytes)
total += l.density
# Store for optional use by the neural network.
self.average = total / float(len(self.lines))
def output(self):
"""Return a string with the useless lines filtered out."""
self.compute_density()
output = StringIO.StringIO()
for l in self.lines:
# Check density against threshold.
# Custom filter extensions go here.
if l.density > 0.5:
output.write(l.text)
This rough filter typically gets most of the lines right. All the headers, footers and sidebars text is usually stripped as long as it’s not too long. However, if there are long copyright notices, comments, or descriptions of other stories, then those are output too. Also, if there are short lines around inline graphics or adverts within the text, these are not output.
这个粗糙的过滤器能够获取大部分正确的文本行。只要页眉、页脚和侧边栏文本并不非常长,那么所有的这些都会被剔除。然而,它仍然会输出比较长的版本声明、注释和对其它故事的概述;在图片和广告周边的比较短小的文本,却被过滤掉了。
To fix this, we need a more complex filtering heuristic. But instead of spending days working out the logic manually, we’ll just grab loads of information about each line and use machine learning to find patterns for us.
要解决这个问题,我们需要更复杂些的启发式过滤器。为了节省手工计算需要花费的无数时间,我们将利用机器学习来处理每一文本行的信息,以找出对我们有用的模式。
Supervised Machine Learning
监督式机器学习
Here’s an example of an interface for tagging lines of text as content or not:
这是一个标识文本行是否为正文的接口界面:
The idea of supervised learning is to provide examples for an algorithm to learn from. In our case, we give it a set documents that were tagged by humans, so we know which line must be output and which line must be filtered out. For this we’ll use a simple neural network known as the perceptron. It takes floating point inputs and filters the information through weighted connections between “neurons” and outputs another floating point number. Roughly speaking, the number of neurons and layers affects the ability to approximate functions precisely; we’ll use both single-layer perceptrons (SLP) and multi-layer perceptrons (MLP) for prototyping.
所谓的监督式学习就是为算法提供学习的例子。在这个案例中,我们给定一系列已经由人标识好的文档——我们知道哪一行必须输出或者过滤掉。我们用使用一个简单的神经网络作为感知器,它接受浮点输入并通过“神经元”间的加权连接过滤信息,然后输后另一个浮点数。大体来说,神经元数量和层数将影响获取最优解的能力。我们的原型将分别使用单层感知器(SLP)和多层感知器(MLP)模型。
To get the neural network to learn, we need to gather some data. This is where the earlier LineWriter.output() function comes in handy; it gives us a central point to process all the lines at once, and make a global decision which lines to output. Starting with intuition and experimenting a bit, we discover that the following data is useful to decide how to filter a line:
我们需要找些数据来供机器学习。之前的LineWriter.output()函数正好派上用场,它使我们能够一次处理所有文本行并作出决定哪些文本行应该输出的全局结策。从直觉和经验中我们发现下面的几条原则可用于决定如何过滤文本行:
Density of the current line.
当前行的密度
Number of HTML bytes of the line.
当前行的HTML字节数
Length of output text for this line.
当前行的输出文本长度
These three values for the previous line,
前一行的这三个值
… and the same for the next line.
后一行的这三个值
For the implementation, we’ll be using Python to interface with FANN, the Fast Artificial Neural Network Library. The essence of the learning code goes like this:
我们可以利用FANN的Python接口来实现,FANN是Fast Artificial Neural NetWork库的简称。基本的学习代码如下:
from pyfann import fann, libfann
# This creates a new single-layer perceptron with 1 output and 3 inputs.
obj = libfann.fann_create_standard_array(2, (3, 1))
ann = fann.fann_class(obj)
# Load the data we described above.
patterns = fann.read_train_from_file('training.txt')
ann.train_on_data(patterns, 1000, 1, 0.0)
# Then test it with different data.
for datin, datout in validation_data:
result = ann.run(datin)
print 'Got:', result, ' Expected:', datout
Trying out different data and different network structures is a rather mechanical process. Don’t have too many neurons or you may train too well for the set of documents you have (overfitting), and conversely try to have enough to solve the problem well. Here are the results, varying the number of lines used (1L-3L) and the number of attributes per line (1A-3A):
尝试不同的数据和不同的网络结构是比较机械的过程。不要使用太多的神经元和使用太好的文本集合来训练(过拟合),相反地应当尝试解决足够多的问题。使用不同的行数(1L-3L)和每一行不同的属性(1A-3A)得到的结果如下:
The interesting thing to note is that 0.5 is already a pretty good guess at a fixed threshold (see first set of columns). The learning algorithm cannot find much better solution for comparing the density alone (1 Attribute in the second column). With 3 Attributes, the next SLP does better overall, though it gets more false negatives. Using multiple lines also increases the performance of the single layer perceptron (fourth set of columns). And finally, using a more complex neural network structure works best overall — making 80% less errors in filtering the lines.
有趣的是作为一个猜测的固定阈值,0.5的表现非常好(看第一列)。学习算法并不能仅仅通过比较密度来找出更佳的方案(第二列)。使用三个属性,下一个SLP比前两都好,但它引入了更多的假阴性。使用多行文本也增进了性能(第四列),最后使用更复杂的神经网络结构比所有的结果都要更好,在文本行过滤中减少了80%错误。
Note that you can tweak how the error is calculated if you want to punish false positives more than false negatives.
注意:你能够调整误差计算,以给假阳性比假阴性更多的惩罚(宁缺勿滥的策略)。
Conclusion
结论
Extracting text from arbitrary HTML files doesn’t necessarily require scraping the file with custom code. You can use statistics to get pretty amazing results, and machine learning to get even better. By tweaking the threshold, you can avoid the worst false positive that pollute your text output. But it’s not so bad in practice; where the neural network makes mistakes, even humans have trouble classifying those lines as “content” or not.
从任意HTML文件中抽取正文无需编写针对文件编写特定的抽取程序,使用统计学就能获得令人惊讶的效果,而机器学习能让它做得更好。通过调整阈值,你能够避免出现鱼目混珠的情况。它的表现相当好,因为在神经网络判断错误的地方,甚至人类也难以判定它是否为正文。
Now all you have to figure out is what to do with that clean text content!
现在需要思考的问题是用这些“干净”的正文内容做什么应用好呢?
2008-05-28
校内网留言版点回复先弹出对话框
今天无意中发现校内网的留言版,点回复之后会弹出一个对话框,估计是工程师在调试的时候加的,然后更新时忘了去掉,抓屏留念。

点留言弹出的对话框

留言对应的js脚本。
2008-05-03
Django模板奇偶行区别样式实现
一个简单的Django模板方法,实现奇偶行不同样式显示。
<ul>
{% for item in objects %}
<li class="{% cycle 'even' 'odd' %}">
{{ item.xxx }}
...
</li>
{% endfor %}
</ul>
这里面cycle会自动的根据上层循环轮询后面给定的list,也就是:“'even' 'odd'..."
转: Python,PIL,ImageMagick,PythonCOM --我们能实现什么
一篇老文了,说了些关于PIL, ImageMagick, Python 的东西,最初发表在python.cn上的。
转自:简单生活 作者:lihuaxia
前阵子,我的一个朋友想要一个web图库(gallery),我本着方便别人也方便自己的原则,给他在众多的opensource方案中选择了php+mysql中gallery的佼佼者:4images。这是个德国软件,php的,图片用文件系统保存,数据关系放在mysql中,程序写得挺好,里面还有自动缩略图片的接口,用的是gd或者imagemagick。本来以为能够满足他所有的需要,后来他告诉我,“急需”一个自动往图片上印上网站的log或者文字的功能。
熟悉php的哥们都知道,gd已经不支持gif了,我的朋友是个美工,很多gif图片,于是我翻看imagemagick的文档,可以办到,嵌了几行代码,实现了。于是他就觉得不满足了,想要个在线剪切、往图片上写字、旋转图片.... 等他说出滤镜的时候,我已经人间蒸发了。
其实,我觉得要实现那些功能并不是不可能。如果给我时间、充分的考虑,是可以做出来的。由网页客户端发送给服务器,需要进行的操作(copy,parse,cut,replace...),具体参数(比如坐标、颜色值、字体、文字....)。由服务端程序执行需要进行的imagemagick命令,比如在php下用system(convert .....)这样,也可以通过php的imagick来实现。
但是,这并不是我最想要的,我觉得要想做出我真正想要的东西,得用python--这个我最喜欢的语言来实现。为什么呢?请听我的理由。
1,python有非常好的图形接口,对于图形的显示、x界面、win界面、客户端应用控件,构造起来非常的容易。
2,真正的“完全面向对象”,对于这种复杂程度的应用,很容易描述。比目前的php4x的非常牵强的面向对象机制,要好得多。
3,数据存储的特点,python的对象存储,可以直接将图像处理过程进行非常直接的描述,我的意思是说,用类描述图片的各种属性,构造各种方法、过程来描述图片处理的操作和过程,用真正完全面向对象的python对象来进行描述。
另外,大家应该都用过photoshop吧,它可以undo,用b/s或者c/s的方式,如何实现undo的功能呢?我觉得对对象的直接存储,是个非常简单的办法。
4,python的执行效率不高,但是在python层面仅仅执行操作命令的生成->解析->解释->发送给图片处理引擎,这些计算,并不是python执行效率的瓶颈。换句话说,python执行中间操作,把繁重的操作留给系统。况且,这些对字符串的操作、对象 属性的存取,恰恰是python擅长的。
1.客户端的实现
当然,b/s方式也有不足,主要在于对鼠标行为的响应支持,很欠缺。对于那些复杂的消息响应,显得无能为力。(如:拖放、 调整角度、调整大小)
1.2 c/s 在鼠标消息方面,就显得游刃有余了。“可变化的布景”就能解决很多问题,那些复杂的鼠标消息,已经有了相应的非常标准的接口。但是,客户端的更新就有些麻烦了,需要重新下载软件。
2.服务端的实现
2.1.1 PIL(Python Imaging Library)
它好得没法说,python爱好者们肯定都是耳熟能详,尤其是那些在zope上面安装过PIL产品的朋友们,对它的图形处理能力肯定是非常的有信心。对于我们这个话题来说,PIL的好处还在于,它也是python的,在于客户端进行交互的时候,会有很多便利。是否能够像zope那样使用xmlrpc传送python对象或者python函数?
也可以修改图片尺寸、旋转、锐化、淡化颜色、增加特殊效果等等,然后把结果存储为各种各样的图片格式。使用ImageMagick可以通过命令行脚本直接调用,也可以通过编程接口,比如:c,c++,perl,java,php,python,ruby等编程语言。已经提供了的Svg性能的高质量2D表达。ImageMagick关注于效果,最小化错误,并且提供了稳定的APIs和ABIs。
它是一套应用程序,文章结尾将介绍convert这个非常有用的命令,通过这个程序,我们可以调用Imagemagick的核心API,来处理图片,这里的处理,是各种图片的操作,包括新图片、拷贝、剪切、合并、生成动画、解析psd图片的图层等等,可以说,所有的我可以做的图片操作,都可以使用convert这个命令来实现。这里必须告诉大家,我基本上是个图片白痴,对图片的处理仅仅停留在缩略图,给图片文字加logo这些基本的操作上面,希望大家能把自己做的图片处理的convert脚本提供出来,供我这样的人使用。
我对python的对象机制数据库的印象还停留在zodb上,单独的使用zodb是一个保存python对象的最简单的方法吧?使用关系数据库来进行对python对象的保存,我还没有进行过这样的应用开发,希望大家能够补充这方面的资料。Z对象数据库现在已经可以单独于zope来使用了吧?另外,我的印象中,还有它的缓慢、recatalog的资源占用的问题。很久不用了,不知道现在的样子。
3.其他问题
这里我只想说,如果采用b/s的架构来实现这个想法,在客户端界面的问题上是很不好解决的。
想想用javascript实现那些复杂的界面消息响应,是啊,肯定可以实现,但是也许在实现以后,一个用netscape的哥们会告诉你,在他的浏览器里头,什么也实现不了。
忘了netscape4和ie4吧,要兼顾它们,可能需要翻看那些已经发黄了的css的知识的书籍,还有厚厚的javascript的早期的浏览器类型对比资料,然后在服务器端判断user-agent,提供给用户不同的javascript+css的实现。当然,还有那些更加难对付的浏览器。即便是ie的5x,都有问题的,从5->5.5的改变中,都有不少的难对付的更改。这不是我们的错,可能也不是任何人的错,谁让着世界上不是只存在一个浏览器呢,想让他们统一html对象机制和接口,是不可能的。我甚至怀疑他们是故意造成现在的状况。除非你不想管其他浏览器或者其他版本的浏览器的用户。
那个bindows不知道能不能提供帮助,我见过有的朋友用它实现了非常了不起的ie浏览器的应用
3.2 在windows下
3.2.1 PIL在windows下的使用
安装python以后在这个页面http://www.pythonware.com/products/pil/index.htm跟据版本选择相应的安装文件python会自动地找到你的python安装,在里面命令行测试一下,就能知道是否安装成功。对图片的路径的引用,需要使用windows路径。
3.2.2 Imagemagick在windows下的使用
ImageMagick在windows下面安装很容易,直接在这里ftp://ftp.imagemagick.org/pub/ImageMagick/beta/ImageMagick-6.0.2-Q16-windows-dll.exe找到windows的安装文件就可以。但是在windows下运行命令行的时候,就需要指定windows下imagemagick的命令来执行了,比如:
c:\im\bin\convert.exe -geometry 120x120 c:\big.jpg c:\small.jpg
3.2.3 在windows下,使用pil或者imagemagick还能做的
我曾经尝试使用pythoncom+pil制作了被python.dll执行的com组件,由asp调用,用来完成在asp下很麻烦的图片处理,缩略等小应用,觉得挺方便的。大概就是按照pythoncom的接口要求,封装几个pil的小方法,注册以后在asp网页里头调用,完成那些以前必须用delphi或者vcvb作的工作。
asp代码:
python代码:
set o = createObject('imageServer')
o.resizeTo(...)
#下面代码中用到的_reg_clsid_是这么来的,在python命令行下:
#>>> import pythoncom
#>>> print pythoncom.CreateGuid()
#{77F5219D-8351-4489-96E6-EBE2915E6DEF}
#这里是命令行取得guid
#需要用一个命令取得classID,然后用命令行注册/注销com
import Image
class ImageServer:
_public_methods_ = ['resizeTo']
_public_attrs_ = ['img']
_reg_progid_ = "ImageServer.Application"
_reg_clsid_ = "{77F5219D-8351-4489-96E6-EBE2915E6DEF}"
def __init__(self):
self.img = None #图片2进制数据或者文件句柄
self.nSize = [None,None] #图片size
self.Type = "" #这里是图片的格式如gif,jpg,psd之类
def resizeTo(self,sp,dp,mx):
self.img = Image.open(sp)
self.Type = self.img.tile[0][0] # 应改成 img.format
self.resize(self.img.size,mx)
self.img.resize(self.nSize).save(dp, self.Type) #这里的调用不好
return self.img
#里面的计算本来是应付图片缩略后大小不一,
def resize(self,size,mx):#排列不好看写得。可能有问题。
if size[0]>=size[1]:
self.nSize[0] = mx
self.nSize[1] = mx*size[1]/size[0]
else:
self.nSize[0] = mx*size[0]/size[1]
self.nSize[1] = mx
if __name__ == '__main__':
import win32com.server.register,sys
if "-unregister" in sys.argv: #这里是注销pythoncom的接口
print "UNRegistering COM Server"
win32com.server.register.UnregisterClasses(ImageServer)
else: #这里是注册pythoncom的接口
print "Registering COM Server"
win32com.server.register.UseCommandLine(ImageServer)
#上面的代码是个半截版本,属性的存取有点问题,运行可能有错误
#原来的代码找不到了
pythoncom是个很好的东西,在windows系统中预先载入python解析器,用com的原理,提供一些服务。由于python的类库非常广大,几乎涵盖了所有的中小型应用,所以,对于有些地方,用起来很方便。需要注意的就是,还没有负载量高的网站用pythoncom的先例,python.dll到底会给机器带来多大的压力,不太清楚。
csdn上有个叫socketref(代码注释作者runonce)的哥们用pythoncom简单包装了一下ado,代码挺有意思,大家可以来看看。网页地址和他的联系方式都已经找不到了,只有代码:
############################################
# 功能: ado数据访问包装
# 日期:2003-01-10
# 创建:runonce
# 历史:
# 2003-01-10 创建
##############################################
from win32com.client import *
import pythoncom
import string
from adoconst import *
#定义参数类型
STRING = adVarChar
INT = adInteger
DOUBLE = adDouble
class PAdo:
""" Ado数据访问包装类
"""
def __init__(self,cnnstr='',bOpen=1):
"cnnstr--ado 数据连接字符串,bopen--是否自动打开"
self.cnnstr =cnnstr
self.adoConn=None
self.rs=None
self.adoConn = Dispatch('ADODB.Connection')
self.rs=Dispatch('ADODB.Recordset')
if bOpen==1 :
self.adoConn.Open(cnnstr)
def Close(self):
self.adoConn=None
self.rs=None
def getTables(self):
" 获取数据库所有表名称"
adoRs = self.adoConn.OpenSchema(20) #取数据库所有表
adoRs.MoveFirst()
ar=[]
while not adoRs.EOF:
ar.append(str(adoRs.Fields.Item('TABLE_NAME')))
adoRs.MoveNext()
return ar
def getFields(self,rs): #recordset
"取记录集字段信息"
fds=[]
for i in range(1,rs.Fields.Count):
fds.append(rs.Fields.Item(i).Name)
return fds
def Select(self,sql):
"""执行查询操作,多参引入
不采用参数占位符方式,传入的sql直接执行
03.0109
"""
self.rs=Dispatch('ADODB.Recordset')
self.rs.Open(sql,self.adoConn)
#
#ar=[]
#while not self.rs.EOF:
# print self.rs.Fields.Item('NAME').Value
# ar.append(self.rs.Fields.Item('NAME').Value)
# self.rs.MoveNext()
return self.rs
def Execute(self,sql,*params):
"""
sql-- sql执行语句,
如果是带参数则形式为 insert into tablename (name) values(:name),同bcb
params --每个参数是一个4元组,代表参数的具体信息 ,
(name,type,size,value) ,撤销size,成为3元组合
params=None,指定sql为正常sql(不带参数占位符号)
使用方法:
ado.Execute(
'insert into basicinfo (name,type,dt,v2) values(?,?,?,?)',['name',STRING,'11'],
['type',STRING,'类型'],
['dt',STRING,'2002-01-12 12:12:01'],
['v2',DOUBLE,111111111.231])
--未进行错误保护
"""
sql = string.upper(sql)
print sql
param = Dispatch('ADODB.Parameter')
cmd = Dispatch('ADODB.Command')
cmd.ActiveConnection = self.adoConn
cmd.CommandText= sql
if(params !=None):
for ele in params: #len(params) 个参数字段带入
print ele[0],ele[1],ele[2]
if ele[1]==STRING:
size = len(unicode(ele[2]))
if ele[1]==INT:
size = 4
if ele[1]==DOUBLE:
size =8
cmd.Parameters.Append(cmd.CreateParameter(ele[0],ele[1],1,size,ele[2]))
cmd.Execute()
def GetRecordCount(self,adors):
"取记录集记录总数"
adors.MoveFirst()
cnt=0
while not adors.EOF:
cnt+=1
adors.MoveNext()
adors.MoveFirst()
return cnt
########################################################
#########################################################
if __name__=="__main__":
ado = PAdo('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=data.mdb;Persist Security Info=False')
rs = ado.Select('select * from basicinfo')
print ado.getFields(rs)
#print ado.GetRecordCount(rs)
#ado.doExec('insert into basicinfo (name) values (?)')
#ado.Execute('insert into basicinfo (name,type,dt,v2) values(?,?,?,?)',['name',STRING,'11'],
#['type',STRING,'类型'],['dt',STRING,'2002-01-12 12:12:01'],['v2',DOUBLE,111111111.231])
4.本文涉及的一些工具
如果你是个python爱好者,别放过它。
地址:http://www.pythonware.com/products/pil/index.htm
手册:http://www.pythonware.com/library/pil/handbook/index.htm
文章:http://www.pythonware.com/products/pil/articles/index.htm
所有子类:
Image 首要类,用来描绘图片对象。
#获取图片旋转显示
import Image
im = Image.open("bride.jpg")
im.rotate(45).show()
import glob
#指定一批图片,按照指定尺寸缩略
for infile in glob.glob("*.jpg"):
file, ext = os.path.splitext(infile)
im = Image.open(infile)
im.thumbnail((128, 128), Image.ANTIALIAS)
im.save(file + ".thumbnail", "JPEG")
ImageChops 图片计算类
ImageColor 颜色类
ImageDraw 平面画图类
#画条灰线输出
import Image, ImageDraw
im = Image.open("lena.pgm")
draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, fill=128)
draw.line((0, im.size[1], im.size[0], 0), fill=128)
del draw
im.save(sys.stdout, "PNG")
ImageEnhance 图片效果类
#锐化图片ImageFile 图片文件存取类
import ImageEnhance
enhancer = ImageEnhance.Sharpness(image)
for i in range(8):
factor = i / 4.0
enhancer.enhance(factor).show("Sharpness %f" % factor)
#复制一幅图片ImageFileIO 图片流类
import ImageFile
fp = open("lena.pgm", "rb")
p = ImageFile.Parser()
while 1:
s = fp.read(1024)
if not s:
break
p.feed(s)
im = p.close()
im.save("copy.jpg")
ImageFilter 图片过滤类
import ImageFilterImageFont 字形类,用于画图
im1 = im.filter(ImageFilter.BLUR)
im2 = im.filter(ImageFilter.MinFilter(3))
im3 = im.filter(ImageFilter.MinFilter)
#获取arial.pil字体,在图片上用这种字体写字ImageGrab 图片抓取类,可以抓屏,或者从剪切板里获取图片
import ImageFont, ImageDraw
font = ImageFont.load("arial.pil")
draw = ImageDraw.Draw(image)
draw.text((10, 10), "hello", font=font)
#检查剪切板中是否有图片ImageOps 图片处理类
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
... got an image ...
elif im:
for filename in im:
try:
im = Image.open(filename)
except IOError:
pass # ignore this file
else:
... got an image ...
else:
... clipboard empty ...
ImagePath 路径队列类
ImagePalette
ImageSequence 队列包装类
ImageStat 图片属性类
ImageTk Tkinter支持类
ImageWin Windows支持类
PSDraw Postscript支持类
不管你用什么语言写代码,了解一下imagemagick真的是有好处的。
地址:http://imagemagick.org/
下载:http://imagemagick.org/www/download.html?
实例:http://imagemagick.org/images/examples.jpg
Imagemagick的python接口:http://sourceforge.net/projects/pylab
另一个Imagemagick的python接口:ftp://ftp.imagemagick.org/pub/ImageMagick/python
convert命令,能够将一幅某种格式的图片进行若干种处理,然后用某种图片格式进行输出。
命令的基本格式: convert [ 选项 ... ] 原始图片 [ 选项 ... ] 输出图片
convert -geometry 120x120 big.jpg small.jpga,需要注意的就是 -geometry 后面的参数是图像大小参数,要想让图片缩略以后显示正常,需要输入正确比例的尺寸。
b,图片的格式,如果需要转换,直接可以通过图片的扩展名的变化,就可以实现,比如,small.gif。
c,gif动画也可以通过这种方式进行直接缩略,但是,所略的效果,需要看gif动画的制作质量,色差,帧数等等因素。
d,quality参数的使用,在缩略的时候,往往会考虑到控制缩略效果,quality这个参数,正是通过给“质量”付值,来控制处理图片的质量。默认得值是75,使用的时候: -quality 80。
convert -delay 10 a1.gif -delay 10 a2.gif -delay 20 a3.gif a.gifa,将a1.gif,a2.gif,a3.gif三个gif图片,按照10,10,20的延迟时间,制作成一个a.gif的动画
b,简便的写法,convert -delay 10 a*.gif a.gif。即将这些图片,按照10的delay制作成gif动画。
convert -bordercolor black -border 25x25 sou.jpg des.gifa,-bordercolor参数是设定便框的颜色
b,-border设定围起来的区域大小
发现一个国人做的学习笔记,很是不错 http://hedong.3322.org/archives/000339.html,介绍的很详细。
主页:http://www.zope.org/Wikis/ZODB/FrontPage
一套很好的javascript开发工具,可以实现非常难得界面。做web的朋友们应该收藏。见过一个外国朋友做了个邮件客户端,挺好的,比outlook好。国人也有不少用这个开发的,似乎用web完全模仿传统界面很时髦?
主页:http://www.bindows.net
lihuaxia 简单生活
2008-01-16
突发奇想
N年之前,玩过一段时间的"第九城市",当时非常热衷于每天爬起来立刻打开电脑,把当天能做的工作都做了,钓鱼,种花,浇水,煮面条,搬砖头......,
然后拿赚到的钱去买东西,然后狂吃"冰淇淋",狂喝"葡萄酒"......,狂升级,狂......,直到有一天起来坐在那一边钓鱼一边想,我过去的一段时间怎么这么无聊呢,每天脸不洗牙不刷的坐在电脑前,看看能钓到P4的CPU还是PIII,呵呵,好能多换几瓶"葡萄酒"喝,疯狂的笑了一阵子之后,散尽家财,把宝物箱中的所有的能送人的都送给了朋友,注销。从此再也没有玩过任何一款网络游戏,虽然九城当时还很稚嫩,也许不算是真正的网络游戏。不过因为它,也成功的造就了我这个,玩过的"最新"的游戏是星际的土人。
2007-12-16
AWStats安装笔记
最近经常要看网站的访问日志,监控网站的流量状况,所以就安装了AWStats, perl写的一个日志分析工具。
自己做网站都需要监控网站的流量情况,看看你的运营努力成果如果,所以就需要一个日志分析工具,选了几个之后决定用AWStats,免费还不叫好用,设置也还简单。界面比较友好,有各种语言版本包括中文,而且可以根据浏览器的语言来自动调用相应语言界面,支持Apache, Squid, IIS等等格式的日志。
我的服务器是Degian Etch,源(source list)里面就有,所以安装很简单:
apt-get install awstats libgeo-ipfree-perl
libgeo-ipfree-perl是ip地址跟国家(地区)的映射表,比通过DNS反相解析域名得到的统计准确,而且速度快,所以推荐安装一下。
然后就可以开始配置了。
首先创建一个站点的配置文件,比如:awstats.mysite.conf,这个可以直接从缺省的/etc/awstats/awstats.conf,copy一个就行了,仍然放在:/etc/awstats/下就可以了。
然后打开两个插件选项:
LoadPlugin="decodeutfkeys"
LoadPlugin="geoipfree"
打开decodeutfkeys插件是为了把通过中文搜索引擎搜索的关键字转换成跟中文界面相同的编码,要不然总是乱码。geoipfree插件是可以统计从不同国家来的ip的数量。
修改几个配置参数:
LogFile="gzip -d </var/log/apache2/mysite.%YYYY-24-%MM-24-%DD-24.log.gz |"
SiteDomain="www.mysite.com"
HostAliases="chedong.com localhost 127.0.0.1"
因为我的日志会每天压缩,所以这里我需要一个管道模式的LogFile,其它默认就可以了。
apache配置:
<VirtualHost YOUR_SERVER_IP:80>
ServerAdmin webmaster@mysite.com
ServerName logs.mysite.com
DocumentRoot /var/www/awstats/
<Directory /var/www/awstats/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog /var/log/apache2/access.log combined
ServerSignature On
Alias /awstats-icon/ /usr/share/awstats/icon/
<Directory /usr/share/awstats/icon>
Options None
AllowOverride None
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
重启apache。
然后开始对日志进行分析:
#/usr/lib/cig-bin/awstats.pl -config=mysite
Update for config "/etc/awstats/awstats.mysite.conf"
With data in log file "gzip -d </var/log/apache2/mysite.2007-12-16.log.gz |"...
Phase 1 : First bypass old records, searching new record...
Searching new records from beginning of log file...
Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
Jumped lines in file: 0
Parsed lines in file: 41110
Found 0 dropped records,
Found 0 corrupted records,
Found 0 old records,
Found 41110 new qualified records.
awstats.pl 会自动去/etc/awstats/下找awstats.mysite.conf这个配置文件来进行日志分析。
这样你就可以打开浏览器访问: http://logs.mysite.com/cgi-bin/awstats.pl?config=mysite 来查看日志了。
这样只有一天的数据,是不够的需要每天定时运行更新程序才可以。
添加crontab任务:
20 0 * * * /usr/lib/cig-bin/awstats.pl -config=mysite
这样就是每天0点20分会自动运行脚本来更新日志了。
如果有多个站点就按照上述方法来创建多个配置文件,然后为每个站点添加一个crontab任务,或者也可以用一个批处理脚本:
20 0 * * * /usr/share/doc/awstats/examples/awstats_updateall.pl now -awstatsprog=/usr/lib/cgi-bin/awstats.pl
这个批处理脚本会对所有的/etc/awstats/awstats.*.conf进行更新。
参考文献:
http://awstats.sourceforge.net/docs/awstats_setup.html
2007-12-10
如何关闭Plone3的即时编辑(Inline-editing)功能
Plone3里面加入了一个很炫的功能──即时编辑(Inline Editing),也就是在文档的查看页(View)状态下,点击文档相应的数据单元(Field),就可以直接编辑而不用刷新页面切换到编辑页(Edit),的确是很方便,但是有的时候太方便了也是个困扰呀。
Plone3.0版本加入很多的Ajax元素,使用户的体验更好了,编辑文档更方便,效率更高,更流畅。
比如:即时编辑(Inline Editing)功能,这个功能使用户可以在不切换到编辑页面就可以直接修改文档的内容,让用户一边浏览网页一边可以进行更改修正网页内容的错误。对于效率的提高是个很好的体验。
即时编辑的功能需要用户登录并且对当前的文档拥有编辑权限,当满足了这些要求之后,用户在查看页面浏览文档的时候,只要把鼠标放到文档内容的上方就可以发现一些动态的效果了,文档的内容会出现一个边框,这时候只要鼠标点击一下就可以在当前页面动态的打开一个小的表单进行编辑了。这个功能是基于Ajax技术的,所以不需要刷新页面,用户不需要等待页面切换载入,所以用户体验很好,效率很好。但是有的时候太方便也会带来一些副作用,比如,当用户不小心点了一下鼠标它也会打开编辑表单,还得再关掉,也很麻烦。所以这里面就需要一个取舍的问题了。不过还是会有朋友问怎么关掉这个功能呢?我把Plone的控制面板里面都看了一遍,也没有找到关于这个功能的控制选项,不知道是有意为之还是没有完全做好,Plone3对于这个功能是默认打开的,所以只要用户登录并且具有修改权限,这个功能就会存在,并且没有一个简单的办法可以关掉。
那么怎么关掉呢,最简单的一个办法,就是不给用户编辑权限,哈哈,这肯定不行呀,总不能连管理员都没有编辑的权限,文档需要改变的时候再去临时把编辑权限打开,这就更麻烦了。所以这个办法不可取,当然可以通过工作流(Workflow)来把已经发布了的文档的,编辑权限(Modify Portal Content)去掉,这样可以部分的解决这个问题,但是仍然有很多不是已发布的文档还是会被这个问题困扰,于是我去查阅了Plone的How-To得到的结论是,想关掉可以,但是需要修改一下相应的模板,添加一个全局模板变量:
tal:define="kss_inline_editable python:False;"
如果整个站都想关掉那就把这个变量加到最高层的模板上比如:main_template.pt 这样就可以在全站范围内关掉这个功能了。
我想了个比较折中的办法,就是添加一个全局的属性(property)来控制这个功能的关闭和打开,以免需要用的时候还要修改模板。首先:在站点的根属性集(Properties)里面添加一个布尔型(boolean)的属性,然后修改上面的变量定义语句为:
tal:define="kss_inline_editable here/kss_inline_editable|python:False;"
这样就是当全局属性kss_inline_editable为真的时候即时编辑功能打开,为假或者属性未定义都是关闭的。通过这样的调整我们现在就可以自由的控制即时编辑功能的开或关了。而且你可以扩展这个全局属性的范围,比如某个文件夹甚至文档都可以定义这个属性,这样,你就可以根据不同的文件夹或者文档的这个属性的取值情况来决定是否打开或者关闭即时编辑功能。当然你也可以通过添加用户属性来控制,就可以按照不同用户的使用习惯来决定了,可能更理想,但是这样做就比较麻烦了,需要进行的修改比较大,可能你做好了,Plone也加入了个控制功能也说不好。有兴趣的朋友可以自己研究一下。
这里检查这个模板变量的代码在:
YourPloneSourceFolder/lib/python/archetypes/kss/fields.py
def _global_kss_inline_editable(self):
...
有兴趣的可以自己去研究一下。
更多关于这个功能的就去研究Plone的KSS包吧,这个是最新的Plone Ajax支持工具包。
参考文献:
http://plone.org/documentation/how-to/how-to-setup-and-use-kss-on-plone-3.0














