分类目录归档:Python

Python Beautiful Soup gb2312 Windows-1252 乱码问题

当初,Python 的编码把我折磨得死去活来,一直准备写一篇文章总结一下。先把我看到的两篇对我最有用的文章贴出来。然后再来慢慢修改整理。
文章1:
Beautiful Soup gb2312乱码问题

http://groups.google.com/group/python-cn/browse_thread/thread/cb418ce811563524

 请注意 gb2312 不是 “gb2312”,凡 gb2312 的请换成 gb18030.
微软将 gb2312 和 gbk 映射为 gb18030,方便了一些人,也迷惑了一些人。

即,实际上该网页是GB18030的编码,所以按照这里:

上午解决了网页解析乱码的问题

http://blog.csdn.net/fanfan19881119/article/details/6789366

(原始出处为:http://leeon.me/a/beautifulsoup-chinese-page-resolve

的方法,传递GB18030给fromEncoding,才可以:

 page = urllib2.build_opener().open(req).read()
soup = BeautifulSoup(page, fromEncoding=”GB18030“)

   而其中,也解释了,为何HTML标称的GBK的编码,但是却解析出来为windows-1252了:

 最近需要写一个python的RSS抓取解析程序,使用了feed parser。但是对于百度新闻的RSS,其编码方式为gb2312,feed parser探测出来的编码却是windows-1252,结果中文内容都是一堆乱码。问题在于,并不是feedparser不能识别出gb2312编码,而是国人们往往将gb2312与gbk编码等同,某些已经使用了gbk编码里的字符的,仍然声称内容为gb2312编码。feedparser对gb2312编码严格遵循gb2312字符集范围,当探测到超出这一范围的字符,便将编码回退到windows-1252。由于百度的RSS实际使用的应该是gbk编码,里面含有超出gb2312范围的字符,于是feedparser便擅自决定了将编码退回windows-1252,导致了中文乱码的现象。

 

文章2:

【整理】Python中实际上已经得到了正确的Unicode或某种编码的字符,但是看起来或打印出来却是乱码

http://www.crifan.com/python_already_got_correct_encoding_string_but_seems_print_messy_code/

 

python中函数参数传递的几种方法

python中函数参数传递的几种方法

Python中函数参数的传递是通过“赋值”来传递的。但这条规则只回答了函数参数传递的“战略问题”,并没有回答“战术问题”,也就说没有回答怎么赋值的问题。函数参数的使用可以分为两个方面,一是函数参数如何定义,二是函数在调用时的参数如何解析的。而后者又是由前者决定的。函数参数的定义有四种形式:

   1. F(arg1,arg2,…)
   2. F(arg2=<value>,arg3=<value>…)
   3. F(*arg1)
   4. F(**arg1)

第1 种方式是最“传统”的方式:一个函数可以定义不限个数参数,参数(形式参数)放在跟在函数名后面的小括号中,各个参数之间以逗号隔开。用这种方式定义的函数在调用的时候也必须在函数名后的小括号中提供相等个数的值(实际参数),不能多也不能少,而且顺序还必须相同。也就是说形参和实参的个数必须一致,而且想给形参1的值必须是实参中的第一位,形参与实参之间是一一对应的关系,即“形参1=实参1 形参2=实参2…”。很明显这是一种非常不灵活的形式。比如:

def addOn(x,y): return x + y

这里定义的函数addOn,可以用addOn(1,2)的形式调用,意味着形参x将取值1,主将取值2。addOn(1,2,3)和addOn (1)都是错误的形式。
第2种方式比第1种方式好一点,在定义的时候已经给各个形参定义了默认值。因此,在调用这种函数时,如果没有给对应的形式参数传递实参,那么这个形参就将使用默认值。比如:

def addOn(x=3,y=5): return x + y”

那么addOn(6,5)的调用形式表示形参x取值6,y取值5。此外,addOn(7)这个形式也是可以的,表示形参x取值7,y取默认值5。这时候会出现一个问题,如果想让x取默认值,用实参给y赋值怎么办?前面两种调用形式明显就不行了,这时就要用到Python中函数调用方法的另一大绝招 ──关健字赋值法。可以用addOn(y=6),这时表示x取默认值3,而y取值6。这种方式通过指定形式参数可以实现可以对形式参数进行“精确攻击”,一个副带的功能是可以不必遵守形式参数的前后顺序,比如:addOn(y=4,x=6),这也是可以的。这种通过形式参数进行定点赋值的方式对于用第1种方式定义的函数也是适用的。
上面两种方式定义的形式参数的个数都是固定的,比如定义函数的时候如果定义了5个形参,那么在调用的时候最多也只能给它传递5个实参。但是在实际编程中并不能总是确定一个函数会有多少个参数。第3种方式就是用来应对这种情况的。它以一个*加上形参名的方式表示,这个函数实际参数是不一定的,可以是零个,也可以是N个。不管是多少个,在函数内部都被存放在以形参名为标识符的tuple中。比如:
对这个函数的调用addOn() addOn(2) addOn(3,4,5,6)等等都是可以的。

与第3种方式类似,形参名前面加了两个*表示,参数在函数内部将被存放在以形式名为标识符的dictionary中。这时候调用函数必须采用key1=value1、key2=value2…的形式。比如:

   1. def addOn(**arg):
   2.     sum = 0
   3.     if len(arg) == 0: return 0
   4.     else:
   5.        for x in arg.itervalues():
   6.           sum += x
   7.     return sum

那么对这个函数的调用可以用addOn()或诸如addOn(x=4,y=5,k=6)等的方式调用。

上面说了四种函数形式定义的方式以及他们的调用方式,是分开说的,其实这四种方式可以组合在一起形成复杂多样的形参定义形式。在定义或调用这种函数时,要遵循以下规则:

   1. arg=<value>必须在arg后
   2. *arg必须在arg=<value>后
   3. **arg必须在*arg后

在函数调用过程中,形参赋值的过程是这样的:
首先按顺序把“arg”这种形式的实参给对应的形参
第二,把“arg=<value>”这种形式的实参赋值给形式
第三,把多出来的“arg”这种形式的实参组成一个tuple给带一个星号的形参
第四,把多出来的“key=value”这种形式的实参转为一个dictionary给带两个星号的形参。
听起来好复杂,实际是是很简单的。很直观,来看例子:

   1. def test(x,y=5,*a,**b):
   2. print x,y,a,b

就这么一个简单函数,来看看下面对这个函数调用会产生什么结果:
test(1) ===> 1 5 () {}
test(1,2) ===> 1 2 () {}
test(1,2,3)  ===> 1 2 (3,) {}
test(1,2,3,4) ===> 1 2 (3,4)
test(x=1)   ===> 1 5 () {}
test(x=1,y=1)  ===> 1 1 () {}
test(x=1,y=1,a=1)   ===> 1 1 () {‘a’:1}
test(x=1,y=1,a=1,b=1)   ===> 1 1 () {‘a’:1,’b’:1}
test(1,y=1) ===> 1 1 () {}
test(1,2,y=1) ===> 出错,说y给赋了多个值
test(1,2,3,4,a=1) ===> 1 2 (3,4) {‘a’:1}