1. 程式人生 > >使用BeautifulSoup爬取“0daydown”站點的信息(2)——字符編碼問題解決

使用BeautifulSoup爬取“0daydown”站點的信息(2)——字符編碼問題解決

snippet sni 結束 編碼錯誤 charset utf 教程 作者 request

上篇中的程序實現了抓取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:\codefile\Soup\0daydown - 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入了下門,註冊了個帳號。準備以後代碼都放在那上面了。


使用BeautifulSoup爬取“0daydown”站點的信息(2)——字符編碼問題解決