Python爬虫Csdn系列III

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

 

下个系列可能就要开始做微博的爬虫了,会涉及到相关的数据处理和分析,希望能顺利点。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。