一. 目标
使用Python提取某CSDN博客的全部文章, 并转换为本地网页(例如一些连接, 是http网页的, 要转成本地的.). (成功提取后可以使用CHM工具把整个博客压成chm文件). 这里以我自己的博客http://blog.csdn.net/bagboy_taobao_com 为目标.
1.1 我这里只按照博客中两种方式提取文章: 文章分类和文章存档.
图1
2. 目标是文章内容, 有了内容后, 怎样显示就可以随意了, 不一定按照博客原来的显示, 当然按照原来的显示也可以.
3. 后续可以把数据添加到数据库保存等等等.....
二. 需要的技术
1. 从网站抓取博客得到HTML字符串.
2. 分析HTML字符串, 提取需要的数据.
3. 提取得到后的数据再转换为本地的数据.
4. 难点: 分析HTML(因为对HTML不太熟悉); 如何转换成本地数据; 网页上的脚本JS可能也有难度; 还有DTD等.
三. 步骤
3.1 获取"文章分类列表"和"文章存档列表"
3.1.1 分析博客主页的HTML
使用浏览器查看http://blog.csdn.net/bagboy_taobao_com 的HTML并保存为Index.html(保存的格式必须为UTF8, 否则会乱码). 双击打开Index.html, 可以正确显示. OK, 可以用文本打开分析.
3.1.2 分析"文章分类"的HTML
<div id="panel_Category" class="panel">
<ul class="panel_head"><span>文章分类</span></ul>
<ul class="panel_body">
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/category/600202">ATL/WTL</a><span>(13)</span></li>
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/category/623494">Boost</a><span>(3)</span></li>
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/category/758331">C++模板</a><span>(3)</span></li>
...
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/category/1502669">大数据</a><span>(0)</span></li>
</ul>
</div>
有什么特点? 那就是http://blog.csdn.net/bagboy_taobao_com/article/category/ , 判断到超连接有这串字符的就是一个分类.
3.1.3 分析"文章存档"的HTML
<div id="panel_Archive" class="panel">
<ul class="panel_head"><span>文章存档</span></ul>
<ul class="panel_body">
<div id="archive_list">
<!--归档统计-->
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/month/2013/11">2013年11月</a><span>(2)</span></li>
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/month/2013/10">2013年10月</a><span>(19)</span></li>
......
<li><a href="http://blog.csdn.net/bagboy_taobao_com/article/month/2008/11">2008年11月</a><span>(6)</span></li>
</div>
</ul>
</div>
有什么特点? 那就是http://blog.csdn.net/bagboy_taobao_com/article/month/ , 判断到超连接有这串字符的就是一个存档.
3.1.4 Python实现提取文章分类列表和文章存档列表
#!/usr/bin/env python
# coding=utf-8
# Python 2.7.3
# 获取博客文章分类列表和文章存档列表
# File: GetCategoryAndMonth.py
import urllib2
import HTMLParser
import httplib
# from HTMLParser import HTMLParser
class CHYGetCategoryAndMonth(HTMLParser.HTMLParser):
def __init__(self, type, list):
'''
type : 0 提取分类列表, 1 提取文章存档
'''
HTMLParser.HTMLParser.__init__(self) # 调用父类的构造函数, 这里调用时有self的
self.type = type
self.ok = False
self.listItem = ["", ""]
self.list = list
def handle_starttag(self, tag, attrs):
if "a" == tag :
for (variable, value) in attrs :
if False == self.ok and (0 == self.type and variable == "href" and value.startswith("http://blog.csdn.net/bagboy_taobao_com/article/category/")) or (1 == self.type and variable == "href" and value.startswith("http://blog.csdn.net/bagboy_taobao_com/article/month/")):
self.ok = True
self.listItem[0] = value
def handle_data(self, data):
if True == self.ok:
self.ok = False
self.listItem[1] = data
self.list.append(self.listItem)
'''
# 测试代码
if __name__ == '__main__':
conn = httplib.HTTPConnection("blog.csdn.net")
# 要模拟成IE发送, 否则CSDN不接受Python的请求
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headersP = { 'User-Agent' : user_agent }
conn.request(method = "GET", url = "/bagboy_taobao_com", headers = headersP)
r1 = conn.getresponse() # 获得响应
htmlByte = r1.read() # 获得HTML
htmlStr = htmlByte.decode("utf8") # 需要转换成utf8编码, 否则分析异常
list = []
my = CHYGetCategoryAndMonth(0, list)
my.feed(htmlStr)
print(list)
'''
遇到的异常情况:
1. CSDN不接受Python的请求, 所以需要模拟IE请求..
2. 得到的HTML文本需要转换为utf8 (htmlStr = htmlByte.decode("utf8")), 否则HTMLParser分析会出错.