【问题】

某人遇到的问题:

关于BeautifulSoup抓取表格及SAE数据库导入的问题(跪求大神帮忙)

简单说就是:

用如下代码:

1
2
3
4
5
6
7
import re,urllib2
from BeautifulSoup import BeautifulSoup
from urllib import urlopen
soup = BeautifulSoup(doc,fromEncoding="GB2312")这里怎么改也没用
a=soup.findAll("td")
print a

但是得到的打印输出还是显示的是乱码:

【解决过程】

1. 此处专门通过实际测试,然后再去查证资料,最终,完整的代码和解释,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Function:
【已解决】BeautifulSoup已经获得了Unicode的Soup但是print出来却是乱码
 
 
Author:     Crifan Li
Version:    2013-05-30
"""
      
import re,urllib2
from BeautifulSoup import BeautifulSoup
from urllib import urlopen
      
def scrapeW3school():
    html = urllib2.urlopen("http://www.w3school.com.cn/html/html_tables.asp");
    #soup = BeautifulSoup(html); #此句效果是一样的:
    #实测结果是:不加fromEncoding,也是可以自动正确(去判断原始的字符编码为GB2312,然后去)解析(出后来的Unicode的soup)的
    soup = BeautifulSoup(html, fromEncoding="GB2312");
    #print "soup=",soup;
    allTdSoup = soup.findAll("td");
    print "type(allTdSoup)=",type(allTdSoup); #type(allTdSoup)= <class 'BeautifulSoup.ResultSet'>,但是实际上算是个List
    print "len(allTdSoup)=",len(allTdSoup); #len(allTdSoup)= 32,此处List的长度是32
    print "allTdSoup=",allTdSoup;
    # allTdSoup= [<td>row 1, cell 1</td>, <td>row 1, cell 2</td>, <td>row 2, ......, <td><a href="/tags/tag_tfoot.asp">&lt;tfoot&gt;</a></td>
    # , <td>瀹氫箟琛ㄦ牸鐨勯〉鑴氥€?/td>, <td><a href="/tags/tag_col.asp">&lt;col&gt;</a></td>, <td>瀹氫箟鐢ㄤ簬琛ㄦ牸鍒楃殑灞
    # 炴€с€?/td>, <td><a href="/tags/tag_colgroup.asp">&lt;colgroup&gt;</a></td>, <td>瀹氫箟琛ㄦ牸鍒楃殑缁勩€?/td>]
  
    #此处,看起来是乱码,但是实际上,此处得到的allTdSoup是个列表,而其中的每个soup,虽然内部编码都是正常的unicode了
    #但还是会打印出来乱码,那是因为:
    #1.先看官网的解释:
    #"当你调用__str__,prettify或者renderContents时, 你可以指定输出的编码。默认的编码(str使用的)是UTF-8。"
    #所以:
    #此处,对于去打印allTdSoup,即去打印一个soup的List,所以,针对List中的每个soup(其本质是个对象),而将其输出为字符串的话,默认是调用其__str__属性
    #所以就相当于:
    #针对allTdSoup中的每个soup:
    #   调用该soup的__str__获得对应的字符串(表示的该soup的内容)
    #最终组合输出你所看到的["xxx", "xxx", ...]之类的结果,
    #其中,"xxx",就是对应的每个soup.__str__的结果
    #而此处的每个soup的__str__的值:
    #如官网所述,默认是UTF-8的编码
    #所以,此处获得的字符串是UTF-8编码的字符串,
    #所以print输出到此处cmd
    #而cmd是GBK编码
    #所以,将UTF-8编码的字符,在GBK的cmd中显示,就显示出乱码了
    #其中:
    #(1)如果对于cmd是GBK不了解,去看:
    #设置字符编码:简体中文GBK/英文
    #(2)如果对于GBK,UTF-8本身不了解,去看:
    #字符编码详解
    #(3)针对于soup本身,其实已经是Unicode编码,所以可以通过官网所说的,指定__str__输出时的编码为GBK,以使得此处正确显示非乱码的中文
    for eachTdSoup in allTdSoup:
        print "type(eachTdSoup)=",type(eachTdSoup); #type(eachTdSoup)= <type 'instance'>,说明类型是BeautifulSoup的实例instance
        print "eachTdSoup.string=",eachTdSoup.string; #输出soup的string属性,即该tag中的字符串内容部分,其本身已经是Unicode,所以可以正常输出非乱码的中文
        print "type(eachTdSoup.string)=",type(eachTdSoup.string); #但是要注意一下,此处不是Unicode类型,而是:type(eachTdSoup.string)= <class 'BeautifulSoup.NavigableString'>
        print "eachTdSoup=",eachTdSoup; #直接输出soup本身,所以相当于:eachTdSoup.__str__ == eachTdSoup.__str__("UTF-8"),所以遇到中文时是乱码
        print "eachTdSoup.renderContents()=",eachTdSoup.renderContents(); #直接输出内容本身,默认也是用的是UTF-8,所以遇到中文时也是乱码
        print "eachTdSoup.__str__('GBK')=",eachTdSoup.__str__('GBK');#专门指定了GBK编码,所以可以正常显示非乱码的中文
    #摘录其中部分输出:
    # type(eachTdSoup)= <type 'instance'>
    # eachTdSoup.string= row 1, cell 1
    # type(eachTdSoup.string)= <class 'BeautifulSoup.NavigableString'>
    # eachTdSoup= <td>row 1, cell 1</td>
    # eachTdSoup.renderContents()= row 1, cell 1
    # eachTdSoup.__str__('GBK')= <td>row 1, cell 1</td>
    # ......
    # type(eachTdSoup)= <type 'instance'>
    # eachTdSoup.string= 定义表格列的组。
    # type(eachTdSoup.string)= <class 'BeautifulSoup.NavigableString'>
    # eachTdSoup= <td>瀹氫箟琛ㄦ牸鍒楃殑缁勩€?/td>
    # eachTdSoup.renderContents()= 瀹氫箟琛ㄦ牸鍒楃殑缁勩€
    # eachTdSoup.__str__('GBK')= <td>定义表格列的组。</td>
    #
    #(4)另外,关于BeautifulSoup可以根据html中的charset猜测其编码的事情,不了解的去看:
    #【整理】关于HTML网页源码的字符编码(charset)格式(GB2312,GBK,UTF-8,ISO8859-1等)的解释
  
if __name__ == "__main__":
    scrapeW3school();

【总结】

所以说:

表面上看起来从BeautifulSoup解析后得到的soup,打印出来是乱码,但是实际上其本身已经是,正确的(从原始的GB2312编码)解析(为Unicode)后的了。

之所以乱码,那是因为,打印soup时,调用的是__str__,其默认是UTF-8,所以输出到GBK的cmd中,才显示是乱码。

总结下来就是:

非得搞懂了:

  • 各种编码本身的逻辑:啥是GBK,啥是UTF-8,啥是Unicode

  • BeautifulSoup的逻辑:可以通过fromEncoding去正确的解析html为Unicode编码的

  • print一个对象的逻辑:内部是调用对象的__str__得到对应的字符串的,此处对应的是soup的__str__

  • soup的__str__的逻辑:默认编码是UTF-8

  • cmd的逻辑:(中文的系统中)编码为GBK

然后才能明白此处的问题的根本的原因的。

【已解决】BeautifulSoup已经获得了Unicode的Soup但是print出来却是乱码的更多相关文章

  1. 【已解决】python中文字符乱码(GB2312,GBK,GB18030相关的问题)

      http://againinput4.blog.163.com/blog/static/1727994912011111011432810/ [已解决]python中文字符乱码(GB2312,GB ...

  2. Microsoft.Office.Interop.Excel, Version=12.0.0.0版本高于引用的程序集(已解决)

    Microsoft.Office.Interop.Excel, Version=12.0.0.0版本高于引用的程序集(已解决) 论坛里的帮助:http://bbs.csdn.net/topics/39 ...

  3. 解决 git 中文路径显示 unicode 代码的问题

    解决 git 中文路径显示 unicode 代码的问题 当被修改的文件中带有中文字符时,中文字符会被转换为 unicode 代码,看不出原来的文件名. 这时,只要配置 :: git config -- ...

  4. 使用Notepad++编码编译时报错(已解决?)

    使用Notepad++编码编译时报错(已解决?) 使用Notepad++编码,编译的时候经常会报错,说什么GBK编码啥啥啥~~~但同样的编码用ECLIPSE就没有问题.再有,用记事本把他保存成ANSI ...

  5. 已解决】Sublime中运行带input或raw_input的Python代码出错:EOFError: EOF when reading a line(转)

    [问题] 在折腾: [已解决]Sublime Text 2中运行Python程序出错:The system cannot find the file specified 的过程中,虽然解决了找不到py ...

  6. 【已解决】Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8

    [问题] 折腾: [已解决]Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8 过程中,增大对应AVD的内存为2G后,结果无法启 ...

  7. Access中出现改变字段“自己主动编号”类型,不能再改回来!(已解决)

    Access中出现改变字段"自己主动编号"类型,不能再改回来! (已解决) 一次把access中的自增字段改成了数值,再改回自增时,提示:在表中输入了数据之后,则不能将不论什么字段 ...

  8. sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决)

    sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决) 出现此错误主要是因为.sql的脚本文件过大(一般都超过100M)造成内存无法 ...

  9. LOL是什么意思? - 已解决 - 搜狗问问

    LOL是什么意思? - 已解决 - 搜狗问问 N A T S U . |分类:QQ工具栏 2009-05-04 LOL是什么意思? 满意答案 Shim Nyong 19级 2009-05-04 LOL ...

随机推荐

  1. Laravel Configuration

    Introduction All of the configuration files for the Laravel framework are stored in the app/config d ...

  2. JMS开发(三):JMS消息的确认方式

    这里单独列出来我也是觉得有点必要的,毕竟JMS总体知识点并不多,这点可能被很多人所忽视. 首选定义:消息的确认是指消息接受者接到消息,并做出了对应的处理之后,它将回送一个确认消息. 对于非事务性会话, ...

  3. Spring Data JPA Tutorial Part Nine: Conclusions(未翻译)

    This is the ninth and the last part of my Spring Data JPA tutorial. Now it is time to take a look of ...

  4. ThinkPad指纹验证在win7无法使用的解决方法

    原先本本装window7 64bit 专业版(正版),但用着用着觉得 很不爽 ,反应特慢.所以决定对本本来次大换血,换成windows server 2008 R2.最后在装指纹验证的时候,使用超级管 ...

  5. LINQ to XML 从逗号分隔值 (CSV) 文件生成 XML 文件

    参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx 本示例演示如何使用 语言集成查询 (LINQ) 和 LINQ to XML 从逗号分隔 ...

  6. Android-WizardPager

    https://github.com/HeinrichReimer/Android-WizardPager

  7. Python基础教程之List对象 转

    Python基础教程之List对象 时间:2014-01-19    来源:服务器之家    投稿:root   1.PyListObject对象typedef struct {    PyObjec ...

  8. UNIX基础知识之时间值

    本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 长期以来,UNIX系统一直使用两种不同的时间值 ...

  9. android:layout_weight总有你不知道的用法.

    都知道weight是权重的意思. 在布局中起到非常重要的作用. 但是这玩意不能嵌套使用, 而且只能使用在LinearLayout中. 下面说说它的几种用法(以下例子全为横排 注意android:lay ...

  10. 关于使用NotificationComat导致android2.3及以下版本无法显示自定义布局的解决方法.

    大伙都知道 android-support-v4为我们提供了很多兼容的解决方案, 其中就有关于通知栏的. NotificationCompat, 顺利成章操刀显示通知. eg: Intent inte ...