使用BeautifulSoup爬取「0daydown」網站的信息(2)——字符編碼問題解決

上篇中的程序實現了抓取0daydown最新的10頁信息,輸出是直接輸出到控制檯裏面。再次改進代碼時我準備把它們寫入到一個TXT文檔中。這是問題就出來了。html

最初個人代碼以下:python

#-*- 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..這種替代了。編碼

問題要追根朔源,我連基本的字符編碼和字符集這些東西都沒有搞清楚,怎麼能解決問題呢?因而我搜索這方面相關文章,給出我以爲好的文章的連接以下:url

字符編碼詳解   這篇文章雖然長,可是做者總結的太詳細了,看了後收穫很大。
命令行

因而我想爲何寫入到文件中就會報錯呢?而命令行輸出就沒有這個問題。難道文件有問題?文件的編碼有問題?我順着這個問題找到了一篇講Python3的文件的文章,很好,連接以下:code

Python3的文件  其中裏面寫到了文件的編碼,原來打開文件時是能夠指定文件編碼的,若是不指定,那麼文件默認採用什麼編碼方式呢?這篇文章作出了詳細的解釋。htm

個人源代碼中打開文件的方式是: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入了下門,註冊了個賬號,準備之後代碼都放在那上面了。utf-8

相關文章
相關標籤/搜索