1. 程式人生 > >python3寫爬蟲程式時,遇到的問題及解決方法

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改