其实之前就对网络爬虫有点兴趣,这次正好用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''
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''">(.+?)'
titleRe=re.compile(reg,re.S)
titleList=re.findall(titleRe,html)
return titleList
def getTime(html):
reg=r'(.+?)'
timeRe=re.compile(reg)
timeList=re.findall(timeRe,html)
return timeList
def getArticleInfo(html):
reg=r'(.+?)'
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)