操作系统:windowAll

编程工具:visual studio 2013

编程语言:VC++

最近博文更新的较频繁,为了防止账号异常引起csdn博文丢失,所以花了点时间做了个小工具来导出博文,用做备份。本文将从源码分析整个实现过程。先看个截图:

操作步骤:

  1. 先在博客地址文本框输入博客地址例如:http://blog.csdn.net/yxstars/,http://blog.sina.com.cn/yxstars/,

    http://www.cnblogs.com/yxstars/
  2. 然后点击确定,将显示共有多少篇博文,例如:[19:32:47]博文113篇
  3. 点击文章列表:将显示所有博文,格式:title,href
  4. 点击导出博文:将导出博文,在当前目录下的blog文件夹中。博文格式为html。
  5. 遍历博文:将遍历所有博文并且显示出来。
  6. 刷新:刷新所有博文,不显示。
  7. 图片:导出的博文,图片下载到本地,博文图片链接到本地。
  8. 列表:支持自定义的列表链接博文(当前目录下有个list.ini,可以自定义链接)。
  9. 刷新次数:自定义,循环次数。
  10. 时间间隔:每次循环sleep时间。

源码分析:

1. 获取对应的url页面源代码,实现如下:

bool CBlogExportDlg::GetUrlStr(CString strUrl, CString& UrlData)
{
CInternetSession session;
CHttpFile *file = NULL;
try{
file = (CHttpFile*)session.OpenURL(strUrl);
}
catch (CInternetException *m_pException){
file = NULL;
m_pException->m_dwError;
m_pException->Delete();
session.Close();
ShowMes("网络连接错误...");
return false;
} if (!file){
ShowMes(strUrl + "获取失败...");
return false;
} CString sRecived;
while (file->ReadString(sRecived) != NULL) {
UrlData += sRecived + "\n";
}
session.Close();
file->Close();
delete file;
file = NULL;
return true;
}

2. 获取的html源码为utf8格式,需要转为ansi格式,C++实现代码如下:

int CBlogExportDlg::ConvUtf8ToAnsi(CString& strSource, CString& strChAnsi)
{
if (strSource.GetLength() <= 0)
return 0; CString strWChUnicode; strSource.TrimLeft();
strSource.TrimRight();
strChAnsi.Empty(); int iLenByWChNeed = MultiByteToWideChar(CP_UTF8, 0,
strSource.GetBuffer(0),
strSource.GetLength(), //MultiByteToWideChar
NULL, 0); int iLenByWchDone = MultiByteToWideChar(CP_UTF8, 0,
strSource.GetBuffer(0),
strSource.GetLength(),
(LPWSTR)strWChUnicode.GetBuffer(iLenByWChNeed * 2),
iLenByWChNeed); //MultiByteToWideChar strWChUnicode.ReleaseBuffer(iLenByWchDone * 2); int iLenByChNeed = WideCharToMultiByte(CP_ACP, 0,
(LPCWSTR)strWChUnicode.GetBuffer(0),
iLenByWchDone,
NULL, 0,
NULL, NULL); int iLenByChDone = WideCharToMultiByte(CP_ACP, 0,
(LPCWSTR)strWChUnicode.GetBuffer(0),
iLenByWchDone,
strChAnsi.GetBuffer(iLenByChNeed),
iLenByChNeed,
NULL, NULL); strChAnsi.ReleaseBuffer(iLenByChDone); if (iLenByWChNeed != iLenByWchDone || iLenByChNeed != iLenByChDone)
return 1; return 0;
}

3. 消息文本框显示

void CBlogExportDlg::ShowMes(CString mes)
{
CTime time;
time = CTime::GetCurrentTime();//Get the current time
CString Times = _T("[") + time.Format("%H:%M:%S") + "]";//Conversion time format int len = MesEdit.GetWindowTextLength();
MesEdit.SetSel(len, len);
MesEdit.ReplaceSel(Times + mes + _T("\r\n"));
}

4. 点击确定按钮后,实现代码

void CBlogExportDlg::OnBnClickedButtonOk()
{
GetDlgItemText(IDC_EDIT_ADDRESS, blogAdr);
ShowBlogAdr();
//blogAdr = ("http://blog.csdn.net/yxstars/");
int pos = blogAdr.Find("http://blog.csdn.net/");
if (pos == -1){
ShowMes("csdn blog地址不对...");
}
blogAdrs = blogAdr; CString urlData;
if (!GetUrlStr(blogAdr, urlData)){
return;
} CFile fs;
if (!fs.Open(strDirPath + "temp", CFile::modeCreate | CFile::modeWrite)){
return;
} fs.Write(urlData, urlData.GetLength());
fs.Close(); CString ansiUrlData;
ConvUtf8ToAnsi(urlData, ansiUrlData);
GetBlogInfo(ansiUrlData); }

5. 根据博客地址,获取源代码后分析,查找博文数目,和博文列表页数。

<!--显示分页 -->

<div id="papelist" class="pagelist">
<span> 113条数据 共6页</span><strong>1</strong> <a href="/yxstars/article/list/2">2</a> <a href="/yxstars/article/list/3">3</a> <a href="/yxstars/article/list/4">4</a> <a href="/yxstars/article/list/5">5</a> <a href="/yxstars/article/list/6">...</a> <a href="/yxstars/article/list/2">下一页</a> <a href="/yxstars/article/list/6">尾页</a>
</div>

从上面的代码中可以获取信息如下:

<span> 113条数据  共6页</span>, 共有113篇博文,共有6页。

<a href="/yxstars/article/list/3">,页面链接地址为/yxstars/article/list/
+ 要显示的页数。

C++代码实现如下:

void CBlogExportDlg::GetBlogInfo(CString& urlData)
{
int pos = urlData.Find("<div id=\"papelist\" class=\"pagelist\">");
if (pos == -1){
ShowMes("获取列表数目失败...");
return;
}
urlData = urlData.Mid(pos + 44);
pos = urlData.Find("条数据");
if (pos == -1){
ShowMes("获取列表条数失败...");
return;
} CString blogListNum = urlData.Left(pos); pos = urlData.Find("条数据 共");
int poss = urlData.Find("页</span>");
if ((poss == -1) || (pos == -1)){
ShowMes("获取列表页数失败...");
return;
} CString listPage = urlData.Mid(pos + 10, poss - pos - 10);
blogListPage = StrToInt(listPage);
ShowMes("博文" + blogListNum + "篇");
}

6. 当点击显示列表时,根据之前的页面地址获取信息。

void CBlogExportDlg::OnBnClickedButtonList()
{
clearMes();
CString urlData, ansiUrlData, listPage;
//http://blog.csdn.net/yxstars/article/list/1
FileListMap.clear();
listNum = 1; for (int i = 1; i < blogListPage + 1; i++){
urlData.Empty();
ansiUrlData.Empty();
listPage.Format("%d", i);
blogAdr = blogAdrs + "/article/list/" + listPage;
ShowBlogAdr();
if (!GetUrlStr(blogAdr, urlData)){
return;
} ConvUtf8ToAnsi(urlData, ansiUrlData);
GetFileList(ansiUrlData);
} }

7. 在每个页面获取文章列表和页面地址。

    <h1>
<span class="link_title"><a href="/yxstars/article/details/38469431">
<font color="red">[置顶]</font>
金融系列12《双币电子现金方案》
</a></span>
</h1>

从上面源码可以看出:

<span class="link_title">后面就是博文链接地址。

</a>前面的就是博文标题。

如果有置顶操作,会多出这部分<font color="red">[置顶]</font>

C++获取源码实现如下:

void CBlogExportDlg::GetFileList(CString& urlData)
{
CString strListNum;
int posF = urlData.Find("<span class=\"link_title\">");
while (posF != -1){
urlData = urlData.Mid(posF + 34);
int posE = urlData.Find("\"");
if (posE == -1){
ShowMes("获取列表失败...");
return;
} CString href = urlData.Left(posE);
posF = urlData.Find("</a>");
if (posF == -1){
ShowMes("获取列表失败...");
return;
} CString title = urlData.Mid(posE+2, posF-posE-2);
posF = title.ReverseFind('>');
if (posF != -1){
title = title.Mid(posF + 1);
}
title.Trim("\n").Trim();
href = "http://blog.csdn.net" + href;
FileListMap[title] = href;
strListNum.Format("%03d", listNum++);
strListNum = (strListNum + ":" + title + " ").Left(45);
ShowMes(strListNum + href);
posF = urlData.Find("<span class=\"link_title\">");
}
}

8. 当点击导出博文时,我们只需把源代码保存为html格式即可,采用多线程实现:

void CBlogExportDlg::OnBnClickedButtonExport()
{
clearMes();
unsigned tid;
unsigned long thd = _beginthreadex(NULL, 0, CBlogExportDlg::WriteCycle, this, 0, &tid);
if (thd != NULL)
{
CloseHandle((HANDLE)thd);
} } unsigned __stdcall CBlogExportDlg::WriteCycle(void* p)
{
CBlogExportDlg* dlg = (CBlogExportDlg*)p;
CString blogFolderPath = dlg->strDirPath + "Blog\\";
if (!PathIsDirectory(blogFolderPath))
{
if (!CreateDirectory(blogFolderPath, NULL))
{
dlg->ShowMes(blogFolderPath + "创建失败...");
return 1;
}
} dlg->stopRun = false;
CString urlData, strList;
int iList = 1;
CFile cf;
std::map<CString, CString>::iterator iter;
for (iter = dlg->FileListMap.begin(); iter != dlg->FileListMap.end(); iter++){
//dlg->blogAdr = iter->second;
//dlg->ShowBlogAdr();
urlData.Empty();
if (!dlg->GetUrlStr(iter->second, urlData)){
return 1;
}
strList.Format("%3d", iList++);
dlg->ShowMes("正在导出第" + strList + "篇博文:" + iter->first);
CString blogPath(iter->first);
blogPath.Replace('\\', '_');
blogPath.Replace('/', '_');
blogPath = blogFolderPath + blogPath + ".html";
if (!cf.Open(blogPath, CFile::modeCreate | CFile::modeWrite)){
dlg->ShowMes("创建文件失败" + blogPath);
return 2;
}
cf.Write(urlData, urlData.GetLength());
cf.Close(); if (dlg->stopRun){
return 1;
} }
return 0;
}

9. 遍历博文时,只需依次访问之前保存的链接即可,实现如下:

void CBlogExportDlg::OnBnClickedButtonRead()
{
clearMes();
unsigned tid;
unsigned long thd = _beginthreadex(NULL, 0, CBlogExportDlg::ReadCycle, this, 0, &tid);
if (thd != NULL)
{
CloseHandle((HANDLE)thd);
}
} unsigned __stdcall CBlogExportDlg::ReadCycle(void* p)
{
CBlogExportDlg* dlg = (CBlogExportDlg*)p;
dlg->stopRun = false;
std::map<CString, CString>::iterator iter;
for (iter = dlg->FileListMap.begin(); iter != dlg->FileListMap.end(); iter++){
dlg->blogAdr = iter->second;
dlg->ShowBlogAdr();
dlg->ShowMes("正在遍历博文:" + iter->first);
Sleep(3000);
if (dlg->stopRun){
return 1;
} }
return 0;
}

CSDN免积分下载地址:

2014.08.01更新: http://download.csdn.net/detail/yxstars/7786309

2014.09.05更新:http://download.csdn.net/detail/yxstars/7867583

文/yanxin8原创,获取更多信息请访问http://yanxin8.com/222.html

博客导出工具(C++实现,支持sina,csdn,自定义列表)的更多相关文章

  1. 用Python编写博客导出工具

    用Python编写博客导出工具 罗朝辉 (http://kesalin.github.io/) CC 许可,转载请注明出处   写在前面的话 我在 github 上用 octopress 搭建了个人博 ...

  2. CSDN博客导出工具 Mac By Swift

    写这篇文章的主要目的是了解Swift语言本身,如何以及Objc和第三方交互框架 必须先用CSDN帐户登录.您可以导出所有的博客文章,加入YAML当首标信息,包括对应标签和分类在头制品信息,和底座式(原 ...

  3. BlogPublishTool - 博客发布工具

    BlogPublishTool - 博客发布工具 这是一个发布博客的工具.本博客使用本工具发布. 本工具源码已上传至github:https://github.com/ChildishChange/B ...

  4. 多平台博客发布工具OpenWrite的使用

    1 介绍 OpenWrite官网 OpenWrite是一款便捷的多平台博客发布工具,可以在OpenWrite编写markdown文档,然后发布到其他博客平台,目前已经支持CSDN.SegmentFau ...

  5. Mac端博客发布工具推荐

    引子 推荐一款好用的 Mac 端博客发布工具. 下载地址 echo 博客对接 这里以cnblog为例.接入类型为metawebblog,access point可以在cnblog的设置最下边找到,然后 ...

  6. Golang拼接字符串的5种方法及其效率_Chrispink-CSDN博客_golang 字符串拼接效率 https://blog.csdn.net/m0_37422289/article/details/103362740

    Different ways to concatenate two strings in Golang - GeeksforGeeks https://www.geeksforgeeks.org/di ...

  7. MetaWeblog博客客户端工具之Windows Live Writer

    吐槽&注意的坑: 刚听说了有这么一个东西,据说Windows Live Writer开源之后就改名为Open Live Writer,我以为Open Live Writer就要比Windows ...

  8. 【转】如何使用离线博客发布工具发布CSDN的博客文章

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  9. 将Medium中的博客导出成markdown

    Medium(https://medium.com)(需要翻墙访问)是国外非常知名的一个博客平台.上面经常有很多知名的技术大牛在上面发布博客,现在一般国内的搬运的技术文章大多数都是来自于这个平台. M ...

随机推荐

  1. 个人收集(转载)CSS中 display:none和visibility:hidden的区别

    visibility和display两个属性都有隐藏元素的功能,display:none和visibility:hidden的区别,简单的总结一句话就是:visibility:hidden隐藏,但在浏 ...

  2. Centos6.5 minicom安装与配置

    Linux下的Minicom的功能与下的超级终端功能相似,适于在通过超级终端对设备的管理以及对嵌入操作系统的升级 1.minicom的安装 查看是否安装:   rpm -qa | grep minic ...

  3. 复习下 AJAX

    什么是AJAx:Asynchronous Javascript and XML中文意思:异步JavaScript 和XML批一种创建交互式网页应用的网页开发技术.AJAX优点1.Ajax 在本质上是一 ...

  4. MVC ueditor的使用(实现上传图片功能)

    之前使用ckeditor不能实现上传图片功能,只要是我不知道怎么使用啦o( ̄ε ̄*),然后就换了ueditor~~,可以实现上传图片功能啦~\(≧▽≦)/~~ 下面是我的步骤:去官网下载最新版uedi ...

  5. 【MySQL】使用mysqlbinlog回滚

    参考:http://wubx.net/?s=mysqlbinlog mysql官方的mysqlbinlog没有回滚的功能,淘宝大牛对官方代码进行了修改使之能够将binlog中的DML操作变成互逆的语句 ...

  6. 10 Code Coverage Tools for C & C++

    Code coverage is a measure used in software testing that describes the degree to which the source co ...

  7. Heavily reliance on forensic tools is risky

    We could take advantage of forensic tools to examine and analyze the evidence, but heavily reliance ...

  8. CentOS 6.x 播放 mp3 音乐 —— 成功

    参考:http://blog.chinaunix.net/uid-14735472-id-3472898.html centos 6.x  添加 rpmforge 源--- CentOS 6.x 安装 ...

  9. PayPal 开发详解(三):在网站上创建【立即付款】按钮

    1.使用[商家帐号]登录https://www.sandbox.paypal.com/ 2.点击[用户信息]->[其他选项]->[我保存的按钮] 3.选择[立即购买按钮事例] 4.[第一步 ...

  10. Android开发教程app下载无法成功创建问题

    本文明来给各位同学介绍一下关于cordova cteate app 时下载失败无法成功创建的解决方法,有碰到此问题的同学可进入参考. 使用如下语句创建一个cordova应用: 代码如下 cordova ...