zoukankan      html  css  js  c++  java
  • 使用BeautifulSoup爬取“0daydown”站点的信息(2)——字符编码问题解决

    上篇中的程序实现了抓取0daydown最新的10页信息。输出是直接输出到控制台里面。再次改进代码时我准备把它们写入到一个TXT文档中。这是问题就出来了。

    最初我的代码例如以下:

    #-*- coding: utf-8 -*-
    #-------------------------------------
    #version: 0.1
    #note:实现了查找0daydown最新公布的10页资源。

    #------------------------------------- #------------------------------------- #version: 0.2 #note:在v0.1基础上输出内容到一个指定TXT文件里 #------------------------------------- import urllib.request import sys import locale from bs4 import BeautifulSoup print(locale.getdefaultlocale()) old = sys.stdout #保存系统默认输出 fp = open("test1.txt",'w') #fp = open("test1.txt",'w', encoding="utf-8") #以utf-8进行文件编码 sys.stdout = fp #输出重定向到一个文件里 for i in range(1,11): url = "http://www.0daydown.com/page/" + str(i) #每一页的Url仅仅需在后面加上整数即可 page = urllib.request.urlopen(url) soup_packtpage = BeautifulSoup(page) page.close() num = " The Page of: " + str(i) #标注当前资源属于第几页 print(num) print("#"*40) for article in soup_packtpage.find_all('article', class_="excerpt"): #使用find_all查找出当前页面公布的全部最新资源 print("Category:".ljust(20), end=''), print(article.header.a.next) #category print("Title:".ljust(20), end=''), print(article.h2.string) #title print("Pulished_time:".ljust(19), end=''), print(article.p.find('i', class_="icon-time icon12").next) #published_time print("Note:", end='') print(article.p.find_next_sibling().string) #note print('-'*50) fp.close() sys.stdout = old #恢复系统默认输出 print("Done!") input() #等待输入。为了不让控制台执行后马上结束。


    执行文件后报错:错误信息例如以下:

    Traceback (most recent call last):
      File "E:codefileSoupdaydown - 0.2.py", line 37, in <module>
        print(article.p.find_next_sibling().string)    #note
    UnicodeEncodeError: 'gbk' codec can't encode character 'xa0' in position 117: illegal multibyte sequence

    从文中能够看出是Unicode编码错误,说gbk不能编码xa0这个字节。就字符编码这个问题我看了好多文章,查阅了好多资料。新手没办法。只是还好弄懂了。

    最初的时候我根本毫无头绪,查看网上的一些文章開始模仿进行encode.decode的。根本没实用。输出仍然有问题,不抛出异常了。可是根本看不到汉字了。全是一些x..这样的替代了。

    问题要追根朔源。我连主要的字符编码和字符集这些东西都没有搞清楚。怎么能解决这个问题呢?于是我搜索这方面相关文章,给出我认为好的文章的链接例如以下:

    字符编码具体解释   这篇文章尽管长,可是作者总结的太具体了,看了后收获非常大。


    于是我想为什么写入到文件里就会报错呢?而命令行输出就没有这个问题。难道文件有问题?文件的编码有问题?我顺着这个问题找到了一篇讲Python3的文件的文章,非常好,链接例如以下:

    Python3的文件  当中里面写到了文件的编码,原来打开文件时是能够指定文件编码的。假设不指定,那么文件默认採用什么编码方式呢?这篇文章做出了具体的解释。

    我的源码中打开文件的方式是:fp = open("test1.txt",'w'),结果抛出异常,从上面抛出的异常能够说明默认打开文件,文件的编码方式是gbk。而GBK是不能编码xa0这个字符的,查了下这个字符,原来是HTML中特有的空字符&nbsp。

    要爬取的网页默认的编码方式是utf-8。说明utf-8是能编码这个字符的。那么我们能够指定文件的编码方式不呢?答案是能够。原来open中还有个參数是encoding,用来指定编码方式,假设我们指定它为utf-8会如何?以下是正确的代码,不同的仅仅是把fp = open("test1.txt",'w')变为了fp = open("test1.txt",'w', encoding="utf-8")。代码例如以下:

    #-*- coding: utf-8 -*-
    #-------------------------------------
    #version: 0.1
    #note:实现了查找0daydown最新公布的10页资源。
    #-------------------------------------
    #-------------------------------------
    #version: 0.2
    #note:在v0.1基础上输出内容到一个指定TXT文件里
    #-------------------------------------
    
    import urllib.request
    import sys
    
    from bs4 import BeautifulSoup
    
    old = sys.stdout        #保存系统默认输出
    #fp = open("test1.txt",'w')
    fp = open("test1.txt",'w', encoding="utf-8")    #以utf-8进行文件编码
    sys.stdout = fp         #输出重定向到一个文件里
    
    for i in range(1,11):
    	url = "http://www.0daydown.com/page/" + str(i)	#每一页的Url仅仅需在后面加上整数即可
    	page = urllib.request.urlopen(url)
    	soup_packtpage = BeautifulSoup(page)
    	page.close()
    	num = " The Page of: " + str(i)		#标注当前资源属于第几页
    	print(num)
    	print("#"*40)
    	for article in soup_packtpage.find_all('article', class_="excerpt"):	#使用find_all查找出当前页面公布的全部最新资源
    		print("Category:".ljust(20), end=''), print(article.header.a.next)   #category
    		print("Title:".ljust(20), end=''), print(article.h2.string)       #title    
    		print("Pulished_time:".ljust(19), end=''), print(article.p.find('i', class_="icon-time icon12").next)  #published_time
    		print("Note:", end='')
    		print(article.p.find_next_sibling().string)    #note
    		print('-'*50)
    
    fp.close()
    sys.stdout = old    #恢复系统默认输出
    print("Done!")
    input() #等待输入,为了不让控制台执行后马上结束。

    执行后,无错误产生,成功写入文件。打开文件,显演示样例如以下:


    能够看出,输出结果与上一篇命令行输出的结果是一样的。圆满解决,OK!!

    另外,今天抽出时间学了下Github。早闻大名,看了下介绍。发现非常强大,跟着官网教程Helloworld入了下门,注冊了个帐号。准备以后代码都放在那上面了。


  • 相关阅读:
    Sprinig.net 双向绑定 Bidirectional data binding and data model management 和 UpdatePanel
    Memcached是什么
    Spring.net 网络示例 codeproject
    jquery.modalbox.show 插件
    UVA 639 Don't Get Rooked
    UVA 539 The Settlers of Catan
    UVA 301 Transportation
    UVA 331 Mapping the Swaps
    UVA 216 Getting in Line
    UVA 10344 23 out of 5
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7040431.html
Copyright © 2011-2022 走看看