python3寫爬蟲程式時,遇到的問題及解決方法
cannot use a string pattern on a bytes-like object
這個錯誤我是發生在以下程式碼:
re.findall(pattern, data)
這個時候如何data的資料型別為bytes,時,就會包這個錯誤,因為它需要的是字串。
我們可以把上面的程式碼改成
type(data)
re.findall(pattern, data)
列印的結果:
<class 'str'>
所以我們要在使用re.findall()方法之前,先把data型別轉為字串str型別。方法:
re.findall(pattern, data .decode('utf-8'))
其中decode和encode方法轉換流程:
decode encode
bytes ------> str(unicode)------>bytes
參考連結:
第二個參考連結中說:現在`python3`中findall引數型別改了為`chart-like`也就是str,
我這裡要說明下,我查了官方文件,即使在python2中也是str型別。引數型別並沒有改。
‘utf-8’ codec can’t decode byte 0x8b in position 1: invalid start byte
出現這個原因是首先你的header裡面配置了
'Accept-Encoding':' gzip, deflate'
其次就是調read()方法時,又調了decode('utf-8')方法,如下:
data = op.read().decode('utf-8')
#因為op.read()資料還沒有解壓再去調decode()方法會報上面異常;
Accept-Encoding這句話:本地可以接收壓縮格式的資料,而伺服器在處理時就將大檔案壓縮再發回客戶端,
瀏覽器在接收完成後在本地對這個檔案又進行了解壓操作。出錯的原因是因為你的程式沒有解壓這個檔案。
重點來了:網上給的答案是,把Accept-Encoding刪除掉
我認為既然都知道是沒有解壓的原因,我們解壓不就行了,何必刪除。
況且像知乎這樣的網站,你爬來的資料不解壓都讀取不出來。
所以我們正確的做法應該是先解壓資料,這裡給出我的解壓程式碼:
# 解壓
def ungzip(data):
try:
print('正在解壓。。。。')
data = gzip.decompress(data)
#data = gzip.decompress(data).decode('utf-8')
print('解壓完畢')
except:
print('未經壓縮,無需解壓')
return data.decode('utf-8')
我這裡讀取的程式碼要這樣寫
data = op.read()
#data = op.read().decode('utf-8')
#千萬別寫成這樣,因為op.read()資料還沒有解壓再去調decode()方法會報上面異常;
data = ungzip(data)
a bytes-like object is required, not ‘list’
首先我給出全部程式碼:
# -*- coding:utf-8 -*-
import re
import urllib
import urllib.request
import gzip
import http.cookiejar
import io
import sys
import string
# gb18030
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# 解壓
def ungzip(data):
try:
print('正在解壓。。。。')
data = gzip.decompress(data)
print('解壓完畢')
except:
print('未經壓縮,無需解壓')
return data.decode('utf-8')
# 獲取xsrf
def getXSRF(data):
cer = re.compile('name="_xsrf" value="(.*)"', flags=0)
strlist = cer.findall(data)
return strlist[0]
# 封裝好請求頭
def getOpener(head):
# deal with the Cookies
cj = http.cookiejar.CookieJar()
pro = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(pro)
header = []
for key, value in head.items():
elem = (key, value)
header.append(elem)
opener.addheaders = header
return opener
# 儲存
def saveFile(data):
data = data.encode('utf-8')
save_path = 'E:\\temp.out'
f_obj = open(save_path, 'wb') # wb表示開啟方式
f_obj.write(data)
f_obj.close()
# 請求頭值
header = {
'Connection': 'Keep-alive',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6',
'Accept-Encoding': 'gzip,deflate',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36',
'Host': 'www.qiushibaike.com'
}
# page = 1
url = 'http://www.qiushibaike.com/hot/'
# 獲得請求頭
# opener = getOpener(header)
# op = opener.open(url)
# data = op.read()
# data = ungzip(data) # 解壓
# _xsrf = getXSRF(data.decode())
try:
opener = getOpener(header)
op = opener.open(url)
data = op.read()
data = ungzip(data)
# op = urllib.request.urlopen(url)
strRex = ('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="articleGender.*?">(.*?)</div>' +
'.*?<div class="content">(.*?)</div>(.*?)<div class="stats.*?class="number">(.*?)</i>')
pattern = re.compile(strRex, re.S)
print(type(data))
items = re.findall(pattern, data)
for item in items:
print(item[0] + item[1] + item[2] + item[3])
# print(item)
print(items)
# saveFile(''.join(str(e) for e in items))#正確的程式碼
saveFile(items)
except Exception as e:
print(e)
出現上面錯誤的原因是執行這句程式碼:
saveFile(items)
而在saveFile函式中,`f_obj = open(save_path, 'wb')`可以看出,“wb”,
以二進位制的模式開啟檔案,並且可寫。而我插入的items是個陣列,所以報錯。
我查閱一些資料後,發現,可以去掉b
引數,也就是變成:
f_obj = open(save_path, 'w')
執行程式碼後發現,它又要求傳入str字串型別。也就是說,當我們不指定已二進位制(b)的形式開啟檔案時,
預設寫入的是str型別。
解決思路:先把要寫入檔案的資料型別轉為str型別,再在saveFile,把str型別轉為bytes。
首先依然是以二進位制開啟檔案,我們在saveFile方法中新增
data = data.encode('utf-8')
encode這個方法就是把str型別轉為bytes型別。
list和tuple元組要利用`''.join()`方法來轉換為str
一開始我寫成
saveFile(items)
結果它又報:
sequence item 0: expected str instance, tuple found
它是說,它在序列中拿第一個元素時,希望得到str字串,結果它發現是元組(tuple);
也就意味著我們要先遍歷陣列把元組轉為str字串型別。
''.join(str(e) for e in items)
這句程式碼從右往左看,先去遍歷items,然後在對每項使用str()方法進行轉換為str型別。
而每項是元組,所以又要使用join函式來把元組轉成str型別`''.join()`.
還有就是元組轉成str字串,列印的效果和沒有轉是一樣的,但是用type(str(e))方法能看出區別。
s = ('a', 'b', 'c')
print(str(s))
print(s)
print(type(str(s)))
print(type(s))
列印結果是:
('a', 'b', 'c')
('a', 'b', 'c')
<class 'str'>
<class 'tuple'>
所以解決辦法就是把saveFile(items)改成:
saveFile(''.join(str(e) for e in items))
最後貼出 list tuple str之間的相互轉換
list()方法是把字串str或元組轉成陣列
tuple()方法是把字串str或陣列轉成元組
>>> s = "xxxxx"
>>> list(s)
['x', 'x', 'x', 'x', 'x']
>>> tuple(s)
('x', 'x', 'x', 'x', 'x')
>>> tuple(list(s))
('x', 'x', 'x', 'x', 'x')
>>> list(tuple(s))
['x', 'x', 'x', 'x', 'x']
列表和元組轉換為字串則必須依靠join函式
>>> "".join(tuple(s))
'xxxxx'
>>> "".join(list(s))
'xxxxx'
>>> str(tuple(s))
"('x', 'x', 'x', 'x', 'x')"#要是使用sublime text 3外掛sublimeREPl,是不會顯示外層的雙引號的。上面同理。
>>>
參考連結:
相關推薦
python3寫爬蟲程式時,遇到的問題及解決方法
cannot use a string pattern on a bytes-like object 這個錯誤我是發生在以下程式碼: re.findall(pattern, data) 這個時候如何data的資料型別為bytes,時,就會包這個錯誤,
使用Junit單元測試及操作MySQL數據庫時出現錯誤及解決方法
靜態 方法 簡單 註解 info 正常 mage 返回 基本上 在一次看Mybatis視頻學習過程中,教學視頻中用到了Junit單元測試,因為剛開始學習,會出現許多錯誤,每次出現錯誤都會上網搜索,但是發現基本上錯誤都是這麽幾種: 1、沒有@Test註解 2、測試方法用s
MyBatis 引數型別為String時常見問題及解決方法
引數為String時的插值問題 假設有下面一Dao介面方法 public Converttce getClassEnergyCoal(String energyType)throws DaoException; 對應的Mapper.xml <select
CStatic控制元件背景透明且改變其文字時,文字重疊解決方法
問題 提出: 最近在專案中將CStatic控制元件設定為背景透明且在一個定時器函式改變其文字,結果CStatic的文字重疊了。解決該問題的方案是:從CStatic類派生自己的靜態文字控制元件。 其實設定背景透明,也就是在CStatic重畫時,返回一個空刷子而已,所以改
python 使用中遇到的問題,記錄及解決方法
ref source ror 遇到的問題 per with open 解決方法 sip oba 1、讀取configparser 配置文件報錯 : 提示: ConfigParser.MissingSectionHeaderError when parsing rsyn
python 使用中遇到的問題,記錄及解決方法
1、讀取configparser 配置檔案報錯 : 提示: ConfigParser.MissingSectionHeaderError when parsing rsyncd config file with global options 解決方法: https://sta
python3 request 爬蟲 httplib.IncompleteRead() 問題的簡單解決方法
起因 在一個迴圈爬取得爬蟲中,隨機出現一個 httplib.IncompleteRead() 錯誤。 分析 查詢了許多資料之後瞭解到,這個是由於 chunked 編碼不完整導致,那麼如何解決這個問題?由於這時候其實資料我們已經拿到了,但是 http_c
Ubuntu14.04安裝、配置ROS Indigo時的錯誤及解決方法
最近這段時間在學習ROS,從書籍到網上資料(網頁,課程,包括2017暑期學校等等),覺得要開始操作一下了就開始安裝雙系統,因為之前的安裝的是虛擬機器VMWARE,覺得太慢太卡簡直了,所以慎重決定(一氣之下),刪掉虛擬機器,在我已有的win8.1系統基礎上在再安裝ubuntu1
ubuntu安裝g2o時出現錯誤及解決方法
安裝G2O可以用高翔在git上的包,一可以從這裡clone下來git clone https://github.com/RainerKuemmerle/g2o.git 然後進入g2o資料夾,執行cmake編譯 mkdir build cd build
VS2012在執行C++Win32程式時出現一閃而過的解決方法
在使用VS2012執行C++Win32程式時,在執行時會出現一閃而過的情況,解決辦法就是: 在_tmain()函式的return 句之前加上:getchar(); 這是目前我試驗後可行的方法,如果有更好的解決方法,歡迎留言。 方法二:Ctrl+F5進行編譯。 有沒有知道為
【OpenCV筆記 11】VS2013中執行OpenCV 3.0時常見錯誤及解決方法
===========2016年10月29日更新================= 本次在筆記本中安裝VS2015和OPENCV 3.1.0參照毛新雲的教程的出現了諸多問題, 最後按照這篇部落格的步
charisma-master中繪points圖時遇到問題及解決方法
1、在專案中使用動態資料程式碼如下: <div class="box col-md-12"> <div class="box-inner"> <div class="box-header well">
VS2010/MFC 利用OLE讀寫excel操作時,手動開啟其他excel文件程式崩掉的問題解決
問題點: (1)我是利用excel儲存程式過程資料,300ms儲存一次。在程式執行過程中,如果手動開啟其他excel檔案,則程式建立的那個excel檔案也會被同時開啟。此時 如果把二者都關閉了,則程式崩潰。為了程式繼續執行,必須保持程式建立的那個excel開啟; (2)
pycharm中導入自寫模塊時,模塊下出現紅線
1-1 自己 其他 技術分享 imp import 情況 bsp 解決辦法 問題描述: 在pycharm中導入自己寫的模塊時,得不到智能提示,並在模塊名下出現下紅線,但是代碼可以執行,錯誤提示為下圖所示: 解決辦法: 出現 以上情況,是因為文件目錄設置
Linux使用yum install 安裝程式時,提示“另外一個程式鎖定了 yum;等待它退出……”
Linux使用yum install 安裝程式時,提示“另外一個程式鎖定了 yum;等待它退出……” 原因: yum命令一次只能安裝一個軟體,所以當你下載安裝第二個軟體包時,系統程序鎖會鎖定yum,這時,關閉程序甚至關閉虛擬機器重啟再執行yum還是會出現同樣情況 解決: 強制採用r
linux 執行程式時,提示not found問題分析
sh: ./test: not found 通常可以通過readelf檢視該程序檔案所以依賴的執行環境,檢查相關路徑是否存在對應的檔案, 注意 1. interpreter是絕對路徑,設定LD_LIBRARY_PATH指向對應目錄對於部分系統則無效 2. Shared library可以是相
寫檔案系統時,核心在寫操作的時候無法進行讀操作
在核心寫程式碼畢竟和在使用者層寫程式碼不太一樣,畢竟核心各種機制很複雜。 今天便遇到了一個問題,本來想在進行寫操作的時候,先判斷本地檔案中的內容,然後根據內容判斷本檔案是否是遠端檔案,類似於軟連線的形式,只是比那個更加複雜,應用於在核心中寫的一個分散式檔案系統。 我需要獲取一
loadrunner執行場景時,常見錯誤及解決方法
目錄 1、Error -27727:.3 2、Error -27728:.3 3、Error -27791:.3 4、Error -27492:.4 5、Error -27498:.4 6、Error -26612:.4
LR執行場景時,21種常見錯誤及解決方法
1、Error -27727: Step download timeout (120 seconds)has expired when downloading resource(s). Set the“Resource Page Timeout is a Wa
我在匯入我們老師寫的程式碼時,他是用的學生機,是win7系統,然後我匯入到eclipse時,發現專案裡面中文都變成了問號形式的亂碼。
我在匯入我們老師寫的程式碼時,他是用的學生機,是win7系統,然後我匯入到eclipse時,發現專案裡面中文都變成了問號形式的亂碼。 我按照別人的指引修改把工作空間的編碼格式改為UTF-8,還有Java檔案也改成了UTF-8,然後還是沒有成功,最後得到老師指引,他說要跟單獨檔案修改resource改