您的位置:首页 > 编程语言 > Python开发

Python爬虫Csdn系列III

2015-04-11 16:11 671 查看

Python爬虫Csdn系列III

By 白熊花田(http://blog.csdn.net/whiterbear) 转载需注明出处,谢谢。

说明:

在上一篇博客中,我们已经能够获取一个用户所有文章的链接了,那么这一节自然就是要将这些博客下载下来咯。

分析:

有了链接下载文章自然是不难。但是,获取的数据该怎么处理?每一篇文章都带有格式换行这些信息,自然,我们存储它们也是要存储其对应的html格式的数据的(注意,我们编辑的带有格式的博客或者其他文本都是以html代码格式存储的)。如何存?使用数据库,每篇文章字数都挺大的,没必要用数据库,还是存储文件更方便。

这里我将下载的每篇博客都取出文章的div部分,然后给这个部分添加必要的html头部及其尾部,将其封装成一个完整的html文本,最后再保存成html格式的文件。这里要注意的就是在html中一定要添加<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />这句话,否则显示的会是乱码。

核心代码在前两篇文章已经提到了,难度也不是很大。

代码:

#-*- coding:utf-8 -*-
import sys
import os
import codecs
import urllib
import urllib2
import cookielib
import MySQLdb
import re
from bs4 import BeautifulSoup
from article import CsdnArticle

reload(sys)
sys.setdefaultencoding('utf-8')

class CsdnCrawler(object):
def __init__(self, author = 'whiterbear'):
self.author = author
self.domain = 'http://blog.csdn.net/'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'}
self.articles = []

#给定url,得到所有的文章lists
def getArticleLists(self, url= None):
req = urllib2.Request(url, headers=self.headers)
response = urllib2.urlopen(req)
soup = BeautifulSoup(''.join(response.read()))
listitem = soup.find(id='article_list').find_all(attrs={'class':r'list_item article_item'})
href_regex = r'href="(.*?)"'
for i,item in enumerate(listitem):
enitem = item.find(attrs={'class':'link_title'}).contents[0].contents[0]
href = re.search(href_regex,str(item.find(attrs={'class':'link_title'}).contents[0])).group(1)
art = CsdnArticle()
art.author = self.author
art.title = enitem.lstrip()
art.href = (self.domain + href[1:]).lstrip()
self.articles.append(art)

def getPageLists(self, url= None):
url = url if url else 'http://blog.csdn.net/%s?viewmode=list'%self.author
req = urllib2.Request(url, headers=self.headers)
response = urllib2.urlopen(req)
soup = BeautifulSoup(''.join(response.read()))
num_regex = '[1-9]\d*'
pagelist = soup.find(id='papelist')
self.getArticleLists(url)
if pagelist:
pagenum = int(re.findall(num_regex, pagelist.contents[1].contents[0])[1])
for i in range(2, pagenum + 1):
self.getArticleLists(self.domain + self.author + '/article/list/%s'%i)

def getAllArticles(self):
#我们创建一个该作者的文件夹来存放作者的文章
if not os.path.exists(self.author):
os.mkdir(self.author)
for subarticle in self.articles:
articleurl = subarticle.href
#依次打开每一篇文章并下载
req = urllib2.Request(articleurl, headers=self.headers)
response = urllib2.urlopen(req)
soup = BeautifulSoup(''.join(response.read()))
article_content = soup.find(id='article_content')
title = subarticle.title.rstrip().encode('utf-8')
#将提取的内容封装成html格式的字符串
article = u'<html><head><title>%s</title><meta http-equiv="Content-Type" \
content="text/html; charset=utf-8" /></head><body>%s</body></html>' % (title, article_content)

fobj = codecs.open(u'%s/%s.htm'%(self.author, title),'w','utf-8')
fobj.writelines(article.encode('utf-8'))
fobj.close()

def main():
csdn = CsdnCrawler(author='whiterbear')#'pongba',可以将填入你想下载的博主的博客
csdn.getPageLists()
csdn.getAllArticles()

if __name__ == '__main__':
main()


结果:

生成了该博主命名的文件夹,文件夹中包含该博主的所有文章。如下图:



随便打开一个文章,显示的效果是这样的:(显示的效果很赞。)



感悟:

1> 中文编码问题。虽然已经了解了几种编码问题的解决方式,但是还是常常被这个问题给卡住。

2> 保持代码的正交性。虽然我还没做过大项目,但是已经能够感受到,如果两个模块的正交性提高,即一个模块的改动并不会影响到另一个模块的正常运行。这样子能够迫使你去思考一种清晰的框架,而不会写了一团糟的代码。

3> 常见的错觉,总觉得这个很简单啊,今天就可以做完啊,结果总是遇到这样那样的问题,还是缺少经验。

4> 其他:保持代码的整洁,尝试迭代,从小的代码开始一点点往上累计新的代码,时刻保持两个版本(其中一个含有大量输出来帮你确定每一步发生了什么)。

 

下个系列可能就要开始做微博的爬虫了,会涉及到相关的数据处理和分析,希望能顺利点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息