其實之前就對網絡爬蟲有點興趣,這次正好用Python來試試。
事先準備:
搭建Python環境
https://www.python.org/downloads/
下載對應自己系統的安裝包,我這裏就直接選3.x版本了
之後就可以開始我們的Python之旅啦
目標是將自己csdn上的博文全部抓取下來
首先獲取自己博文列表的網頁源碼,因爲抓取時會有編碼問題,所以這裏直接將返回的html數據轉換爲utf-8編碼,這樣中文就不會變成unicode編碼形式了
import urllib.request
import re
import sys
def getHtmlInfo(url):
print('url:'+url)
return str(urllib.request.urlopen(url).read(),'utf-8')
html=getHtmlInfo("http://blog.csdn.net/yeyinglingfeng?viewmode=contents")
查看網頁源代碼後得知每篇博文的url所在
//目錄視圖下每篇文章的url
<h1>
<span class="link_title"><a href="/yeyinglingfeng/article/details/76212176">
(6)birt筆記 - 通過傳遞變量來動態修改數據集SQL
</a>
</span>
</h1>
......
知道大致位置之後就可以使用正則表達式來篩選出所有的博文url
()表示分組,將括號的內容捕獲到分組當中
.+表示至少是一個任意字符
?爲懶惰查找,即匹配即可能少的字符串
def getArticleUrl(html):
reg=r'<span class="link_title"><a href="(.+?)">'
articleRe=re.compile(reg)
articleUrlList=re.findall(articleRe,html)
return articleUrlList
articleUrlList=getArticleUrl(html)
url中還缺少一部分,直接定義一個字符串,之後拼接上去即可
htmlStr='http://blog.csdn.net'
然後就可以通過和抓取http://blog.csdn.net/yeyinglingfeng?viewmode=contents一樣的方式來遍歷抓取博文
for articleUrl in articleUrlList:
articleHtml=getHtmlInfo(htmlStr+articleUrl)
然後進入一片自己的博文,查看源代碼,看下具體的正文部分在哪裏,然後用正則或者字符串截取操作來獲取正文即可,這裏因爲我的csdn博文中還有各種代碼塊,圖片,字體,所以正文中混着很多html代碼,這裏處理起來有點麻煩,大致思路也是正則去篩,就是類型有點多,應該會花點時間,這裏就直接篩正文部分了
def saveInfo(info,fileName):
try:
fileAll='d:\\1\\python\\'+fileName+'.txt'
print(fileAll)
with open(fileAll,'w',encoding='utf-8') as file_write:
file_write.write(info)
except:
print('error:something faile')
def getTitle(html,str):
reg=r'<span class="link_title"><a href="'+str+'">(.+?)</a>'
titleRe=re.compile(reg,re.S)
titleList=re.findall(titleRe,html)
return titleList
def getTime(html):
reg=r'<span class="link_postdate">(.+?)</span>'
timeRe=re.compile(reg)
timeList=re.findall(timeRe,html)
return timeList
def getArticleInfo(html):
reg=r'<div id="article_content" class="article_content tracking-ad" data-mod=popu_307 data-dsm = "post" >(.+?)</div>'
articleRe=re.compile(reg,re.S)
articleList=re.findall(articleRe,html)
return articleList
#博文發表時間
time=getTime(articleHtml)[0].replace(':','.')
#博文標題
title=getTitle(articleHtml,articleUrl)[0].replace(' ','').replace('\r\n','').replace(':',' ').replace('/',' ')
#博文保存時用的文件名
fileName=time+' '+title
#博文正文內容
articleInfo=getArticleInfo(articleHtml)[0]
#保存博文
saveInfo(articleInfo,fileName)
整體完畢,對博文的正文部分,還需要進行更加細緻的篩選,剔除掉多餘的html代碼。所用到東西其實很少,比較重要的是urllib.request.urlopen(url)抓取頁面源代碼,在2.X中是import urllib urllib.urlopen(url)。其餘就是對Python數組,正則的運用了,拿來熟悉Python還是不錯的。
過程中遇到很多比較抓狂的編碼問題,比如在直接抓取博文後進行保存時,因爲我這裏使用cmd跑的Python,而cmd默認編碼應該是GBK,然後就會報’Xxxx’字符無法轉換爲gbk的問題,然後不知道的就很抓狂了,明明上面基本全用的utf-8,這個gbk是哪裏跑出來的= =。這時在with open文件時加上utf-8編碼應該就能解決大部分類似問題,不行的話還需要將Python默認編碼設置爲utf-8。然後在截取返回的頁面源碼時,有時需要去掉包含的回車。一般都默認是’\n’,但是這裏是’\r”\n’,之前我在用replace去除多餘回車時,就與到了殘留了’\r’,然後獲得的字符串在與其他字符串進行拼接時,會出現覆蓋現象,大致就是
A='1234567'
B='AB\r\nC'
B=B.replace('\n','')
print(A+B)
#輸出
ABC4567
#大致這樣的意思,當時找問題的地方簡直抓狂,最後才發現回車還附帶\r = =
總感覺之後編碼問題會是一個大坑= =
整體代碼文件
https://github.com/SecondMagic/-1-python-csdn
10.25更新
使用HTMLParser對截取到的正文部分進行進一步的篩選,去除多餘的html
繼承HTMLParser,並對handle_data方法進行重寫,handle_data方法在遇到html標籤中間的文本內容時將會觸發,這裏將獲得的文本內容拼接成正文,還會遇到空行較多的問題,還有原代碼塊部分會出現很多換行,需進一步進行處理
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.htmlStr = ''
def handle_data(self, data):
self.htmlStr+=(data+'\n')
....
#articleInfo爲獲取到的含html文本的正文部分
parser = MyHTMLParser()
parser.feed(articleInfo)
parser.close()
saveInfo(parser.htmlStr,fileName)
大致效果對比