Python的一次新浪博客爬蟲實戰(zhàn)(一)

今天在翻看Evernote的筆記時,看到之前剪輯的一位加國移民文章頗為有趣和實用。于是心血來潮,寫個爬蟲把所有文章都保存下來,哪知道過程中遇到了各種無奈問題,遂寫篇博客以記錄學(xué)習過程。

坑1:bs4的局限性

打算爬的這個新浪博客,原始URL如下:
rootURL = 'http://blog.sina.com.cn/s/articlelist_1750617077_0_1.html'

用瀏覽器查看了一下get下來頁面的html,里面很標準的用<a標簽包含了每篇文章的鏈接。
之前有用BeautifulSoup和Requests的經(jīng)驗,因此很自然的準備用上這兩個工具,利用bs4的解析標簽?zāi)芰?,把所有的uri全部提取出來

from bs4 import BeautifulSoup    
import requests

r = requests.get(URL)    
html = r.text    
bs = BeautifulSoup(html).find_all('a')    
for u in bs:    
  uri = item.get('href')

然而,想象很美好,現(xiàn)實很骨感。拿到的uri是None,也就是說,毛都沒有解析出來。這可有點奇怪了,遂想起bs4的一些局限性,仔細對照了一下博客的html源碼,原來<a全部包含在js里了,難怪bs4毫無作用(坑1:bs4對包含在js里的標簽毫無卵用)。

坑2:中文亂碼

既然bs4對這個博客無法作用,只有采用方案2:正則表達式。
根據(jù)html源碼,寫出正則:

re_blogs = 'target="_blank"\s*href="(.+.html)">(.+)</a></span>'

用正則parser html的函數(shù):

def parseHtml(RE, URL):        
  RE_STRING = RE       
  try:            
    req = requests.get(URL)
    html_doc = req.content            
    info = re.findall(RE_STRING, html_doc)            
    return info       
  except Exception as e:            
    print(e)            
    return None

這下總可以了吧?結(jié)果,依然沒有拿到所有的uri。一度懷疑是自己的正則寫錯了,可是反復(fù)用在線正則工具進行比對,都沒有問題。此時博主心中已經(jīng)一千頭草泥馬跑過了,設(shè)斷點debug!結(jié)果發(fā)現(xiàn)問題出在了req.content問題上,其賦給html_doc的中文部分是亂碼,所以導(dǎo)致re.findall出錯。查看了百度上的一些解釋,猜測是encode格式的問題,加了如下一個debug flag:

req = requests.get(URL)    
print(req.encoding)                
html_doc = req.content

果然,print出來的是一種ISO-8859-1的格式,時間關(guān)系也沒深究了,直接轉(zhuǎn)utf-8搞起

def parseHtml(RE, URL):        
  RE_STRING = RE       
  try:            
    req = requests.get(URL)
    html_doc = str(req.content,'utf-8')#就是這里改動了一點點           
    info = re.findall(RE_STRING, html_doc)            
    return info       
  except Exception as e:            
    print(e)            
    return None

此時終于把所有的uri取出來了!

坑3:file.write()亂碼##

繼續(xù)完善代碼,主要考慮到翻頁如何實現(xiàn),繼續(xù)用萬能的正則:
設(shè)計提取下一頁的正則表達式;
re_next_page = '<a\s*(href=".+.html)"\s*title=".+">\d</a>'
由于新浪博客實在是格式不規(guī)整,html源碼里缺少換行符,原本應(yīng)該正常解析成3個的翻頁url,愣是被搞成了一個連在一起的四不像,如下這樣:
title="跳轉(zhuǎn)至第 2 頁">2</a></li><li><a title="跳轉(zhuǎn)至第 3 頁">3</a></li><li><a href="http://blog.sina.com.cn/s/articlelist_1750617077_0_4.html
只好繼續(xù)寫一個把uri分離的正則:
re_string = 'href="(.*?)"'
把所有頁鏈接,存到一個list中:

all_urls = parseHtml(re_next_page,rootURL)
pages = re.findall(re_string,all_urls[0])#pages is a list
pages.append(rootURL)

接著是從url中保存html的函數(shù):

def getHtmlFromLink(link,name):
    for i,url in enumerate(link):
        req = requests.get(url)
        html_doc = str(req.content, 'utf-8')#子鏈接的內(nèi)容
        html_name = name[i]
        file_path = 'D://blogs//'+html_name+'.html'
        f = open(file_path,'w')
        f.write(html_doc)
        f.close()

最后是main部分

link = []
name = []
for url in pages:
    blogs = parseHtml(re_blogs, url)
    for uri in blogs:
        link.append(uri[0])
        name.append(uri[1])

getHtmlFromLink(link,name)

高潮來了,看著爬蟲開始工作并保存,心里爽爽爽!??!然后用瀏覽器打開保存下來的一個html,他媽的亂碼又來了?。?!
這里筆者就不是很能理解了,已經(jīng)把要寫入filestring都用utf-8編碼好了,為啥中文還是亂碼了?!
在百度上苦尋答案依然無所獲,和一個朋友交流了一下,試著修改了一下write方法參數(shù)

f = open(file_path,'w',-1,'utf-8')

終于正常了,媽蛋!~!


點擊查看源網(wǎng)頁

至此,完成了一個博客所有文章的爬取過程,深刻描述了三個大坑以及筆者的心路歷程。
細心的你們一定發(fā)現(xiàn)了,圖片好像還沒保存到本地呢。這個準備放到下一次的文章中咯~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容