最近开始学习Python的爬虫,本来想着从基本的各种语法开始学习的但是在逛知乎的过程中发现了一个帖子是就是关于如何入门Python爬虫,里面有一个回答,这里面说的就是““入门”是良好的动机,但是可能作用缓慢。如果你手里或者脑子里有一个项目,那么实践起来你会被目标驱动,而不会像学习模块一样慢慢学习”,所以我决定了不从基础模块一个一个慢慢学习,直接从Python爬虫的一个一个小程序学习,若有不懂的地方就往前面基础部分翻。我慢慢发现其实很多内容都是相互联系的,而且在学习基础部分的时候不会在意这个东西究竟有什么作用而只是知道有这个一个东西存在。但是如果是自己实践起来,就能更深刻理解。
话不多说,我第一个爬虫程序参考了很多资料,目标是把一个人的新浪博客里的所有文章都保存下来。网络上面有教育机构的视频也是这么说的,但是我看了视频之后才发现视频的标题只是一个噱头,只是保存了博客所有文章的html网址在一个文件夹,而我希望是可编辑的文本格式。然而这本来就是难度等级不同的(起码对于刚接触Python语言的我而言)所以我决定自己参考资料写一个。
我以韩寒博客为例子。
思路是首先成功抓取一篇文章的内容(包括标题和正文内容),然后是抓取博客目录第一页一整页的文章,这里涉及一个问题是要先获得每篇文章的url然后再抓取文章,最后是观察不同页码的博客目录,找出共同点写一个函数对每一页都进行抓取,最后就大功告成。
[python]view plain copy
def getText(self,url):
text=urlopen(url).read().decode('utf-8')
start=text.find(u"")
print start
end=text.find(u"")
print end
text=text[start:end]
text = re.sub(re.compile('
'),"\n ",text)
text = re.sub(re.compile('
'),"\n ",text)
text=re.sub(r']*>.*?| ','',text)
text=re.sub(r'&[^>]*?\;',' ',text)
return text.encode('utf-8')
这个函数就是获取一篇文章的内容
[python]view plain copy
def getUrl(self,page):
pattern =re.compile('.*?.*?.*?',re.S)
items = re.findall(pattern,page)
urls = []
for item in items:
url = item
urls.append(url.encode('utf-8'))
#print url
return urls
这个函数是获取博客目录所有文章url
[python]view plain copy
def getContent(self,page):
pattern = re.compile('.*?(.*?).*?',re.S)
items = re.findall(pattern,page)
contents = []
for item in items:
contents.append(content.encode('utf-8'))
#print content
return contents
同理这是获取文章的标题
最后贴上源码
[python]view plain copy
# -*- coding: cp936 -*-
__author__ = 'Thor'
# -*- coding:utf-8 -*-
import urllib
import urllib2
import re
from urllib import urlopen
class Tool:
#去除img标签,7位长空格
removeImg = re.compile('| |')
#删除超链接标签
removeAddr = re.compile('|')
#把换行的标签换为\n
replaceLine = re.compile('|
|
|
')
#将表格制表替换为\t
replaceTD= re.compile('')
#把段落开头换为\n加空两格
replacePara = re.compile('
')
#将换行符或双换行符替换为\n
replaceBR = re.compile('
|
')
#将其余标签剔除
removeExtraTag = re.compile('')
def replace(self,x):
x = re.sub(self.removeImg,"",x)
x = re.sub(self.removeAddr,"",x)
x = re.sub(self.replaceLine,"\n",x)
x = re.sub(self.replaceTD,"\t",x)
x = re.sub(self.replacePara,"\n ",x)
x = re.sub(self.replaceBR,"\n",x)
x = re.sub(self.removeExtraTag,"",x)
#strip()将前后多余内容删除
return x.strip()
class XLBK:
def __init__(self,baseUrl,articleTag,fileName):
self.baseURL=baseUrl
self.tool=Tool()
self.file=None
self.article=1
self.defaultTitle=u'新浪博客'
self.articleTag=articleTag
self.fileName=fileName
def getPage(self,pageNum):
try:
url=self.baseURL+str(pageNum)+'.html'
print url
request= urllib2.Request(url)
response=urllib2.urlopen(request)
return response.read().decode('utf-8')
except urllib2.URLError ,e:
if hasattr(e,"reason"):
print u"连接新浪博客失败,错误原因",e.reason
return None
def getTitle(self,page):
pattern = re.compile('blogname.*?blognamespan.*?>(.*?)', re.S)
result = re.search(pattern,page)
print "title"+result.group(1).strip()
if result:
return result.group(1).strip()
else:
return None
def getPageNum(self,page):
pattern= re.compile(ur'共(.*?)页',re.S)
result = re.search(pattern,page)
if result:
#print "pagenum"+result.group(1).strip()
return result.group(1).strip()
else:
print result
return 1
def getContent(self,page):
pattern = re.compile('.*?(.*?).*?',re.S)
items = re.findall(pattern,page)
contents = []
for item in items:
contents.append(content.encode('utf-8'))
#print content
return contents
def getUrl(self,page):
pattern =re.compile('.*?.*?.*?',re.S)
items = re.findall(pattern,page)
urls = []
for item in items:
url = item
urls.append(url.encode('utf-8'))
#print url
return urls
def getText(self,url):
text=urlopen(url).read().decode('utf-8')
start=text.find(u"")
print start
end=text.find(u"")
print end
text=text[start:end]
text = re.sub(re.compile('
'),"\n ",text)
text = re.sub(re.compile('
'),"\n ",text)
text=re.sub(r']*>.*?| ','',text)
text=re.sub(r'&[^>]*?\;',' ',text)
return text.encode('utf-8')
def setFileTitle(self,title):
if title is not None:
self.file = open(title + ".doc","w")
else:
self.file = open(self.defaultTitle + ".doc","w")
def writeData(self,contents,urls):
for item in contents:
if self.articleTag == '1':
articleLine = "\n" + str(self.article) + u"--------------------------------------------------------------------------------\n"
#print item
#print urls[contents.index(item)]
text=self.getText(urls[contents.index(item)])
print text
self.article += 1
def start(self):
indexPage = self.getPage(1)
pageNum = self.getPageNum(indexPage)
title = self.getTitle(indexPage)
self.setFileTitle(self.fileName)
if pageNum == None:
print "URL已失效,请重试"
return
try:
print "该博客共有" + str(pageNum) + "页"
for i in range(1,int(pageNum)+1):
print "正在写入第" + str(i) + "页数据"
page = self.getPage(i)
contents = self.getContent(page)
urls =self.getUrl(page)
self.writeData(contents,urls)
except IOError,e:
print "写入异常,原因" + e.message
finally:
print "写入任务完成"
print u"打开一个新浪博客的博文目录\n如http://blog.sina.com.cn/s/articlelist_1866629225_0_1.html \n那么该博客的代号为1866629225_0_ \n请输入博客代号"
baseURL = 'http://blog.sina.com.cn/s/articlelist_' + str(raw_input(""))
articleTag = raw_input("是否写入文章编号信息,是输入1,否输入0\n")
fileName=raw_input("请输入保存文档的名称\n")
xlbk = XLBK(baseURL,articleTag,fileName)
xlbk.start()
最后就可以坐等收录文章。
图片1
突然有种发现新大陆的感觉。
图片2
ps:第一次写博客文章都不知道原来插入图片要替换文本不然怎么上传和copy paste都无效。
总结一下,这是我自己动手的第一个爬虫小脚本,只是用了urllib,urllib2最基本的类库,当然后来才知道有更多方便的如xpath,beautifulsoup这些,目前都在深入研究当中。
欢迎指出问题。
领取专属 10元无门槛券
私享最新 技术干货