近來接到一個小項目,讀取目標文件中每一行url,並逐個請求url,拿到想要的數據。
#-*- coding:utf-8 -*- class IpUrlManager(object): def __init__(self): self.newipurls = set() #self.oldipurls = set() def Is_has_ipurl(self): return len(self.newipurls)!=0 def get_ipurl(self): if len(self.newipurls)!=0: new_ipurl = self.newipurls.pop() #self.oldipurls.add(new_ipurl) return new_ipurl else: return None def download_ipurl(self,destpath): try: f = open(destpath,'r') iter_f = iter(f) lines = 0 for ipurl in iter_f: lines = lines + 1 self.newipurls.add((ipurl.rstrip('\r\n')) #log記錄讀取了多少行IP url #print lines finally: if f: f.close()
咋一眼看code寫的沒問題,每一個url 增加進newipurls set集合中。但是請求的過程中,requests.get后,會出現如下錯誤:
raise InvalidSchema("No connection adapters were found for '%s'" % url)
后來發現每次都是第一行的url請求失敗。然后打印print 請求的url。也沒發現異常。然后從根源上去找,好吧,print打印newipurls set集合看看。
果然,問題就在這里。
奇怪,為什么這個URL前面為默認加上了\xef\xbb\xbf 這幾個字符呢?
上網看了一些資料,原來在python的file對象的readline以及readlines程序中,針對一些UTF-8編碼的文件,開頭會加入BOM來表明編碼方式。
何為BOM?
所謂BOM,全稱是Byte Order Mark,它是一個Unicode字符,通常出現在文本的開頭,用來標識字節序(Big/Little Endian),除此以外還可以標識編碼(UTF-8/16/32)。
其實如果大家有UltraEdit tool可以發現,在另存為文件的時候,可以保存為UTF-8 和UTF-8 無BOM的文件。
如果將文件另存在UTF-8的格式,則文件的開頭默認會增加三個字節\xef\xbb\xbf。
怎么檢測該文件是否為UTF-8 帶BOM的呢?
import codecs def download_ipurl(self,destpath): try: f = open(destpath,'r') iter_f = iter(f) lines = 0 for ipurl in iter_f: lines = lines + 1 if ipurl[0:3] == codecs.BOM_UTF8: self.newipurls.add((ipurl.rstrip('\r\n')).lstrip('\xef\xbb\xbf')) #print self.newipurls #log記錄讀取了多少行IP url #print lines finally: if f: f.close()
引用codecs模塊,來判斷前三個字節是否為BOM_UTF8。如果是,則剔除\xef\xbb\xbf字節。
其實大家可以通過其他方式剔除BOM字節,我寫的比較粗糙。