自己动手编写优快云博客备份工具-blogspider之源码分析(2)

本文详细解析了优快云博客备份工具的源码,包括如何打印信息、释放内存、下载主页并解析必要信息等核心部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自己动手编写优快云博客备份工具-blogspider之源码分析(2)

分类: 优快云博客备份工具   4577人阅读  评论(5)  收藏  举报
作者:gzshun. 原创作品,转载请标明出处!
来源:http://blog.youkuaiyun.com/gzshun


唐僧:你想要啊?悟空,你要是想要的话你就说话嘛,你不说我怎么知道你想要呢,虽然你很有诚意地看着我,可是你还是要跟我说你想要的。你真的想要吗?那你就拿去吧!你不是真的想要吧?难道你真的想要吗?…… 
悟空:我Kao!


在开篇,先happy下,有个好心情,才能天天向上,奋发图强,自强不息。

继《自己动手编写优快云博客备份工具-blogspider》与《自己动手编写优快云博客备份工具-blogspider之源码分析(1)》博文后,继续贴出处理的一些函数,原理很简单。

一.在博客的下载过程中,打印了一些信息到屏幕,也保存到了*.log文件

[cpp]  view plain copy
  1. /********************************************************* 
  2. 将爬虫链表的内容打印到log文件,格式为"csdn_id.log",比如 
  3. 我的博客的地址为: "gzshun.log" 
  4. *********************************************************/  
  5. static void print_spider(blog_spider *spider_head)  
  6. {  
  7.     char file[BUFSIZE] = {0};  
  8.     char tmpbuf[BUFSIZE] = {0};  
  9.     blog_spider *spider;  
  10.     FILE *fp;  
  11.   
  12.     sprintf(file, "%s.log", csdn_id);  
  13.   
  14.     fp = fopen(file, "a+");  
  15.     if (NULL == fp) {  
  16.         #ifdef SPIDER_DEBUG  
  17.         fprintf(stderr, "fopen: %s\n", strerror(errno));  
  18.         #endif  
  19.         return;  
  20.     }  
  21.       
  22.     setvbuf(fp, NULL, _IONBF, 0);  
  23.     fseek(fp, 0, SEEK_END);  
  24.       
  25.     spider = spider_head->next;  
  26.     while (spider) {  
  27.         fprintf(fp, "%d:\n"  
  28.                     "%-15s : %s\n"  
  29.                     "%-15s : %s\n"  
  30.                     "%-15s : %s\n"  
  31.                     "%-15s : %d\n"  
  32.                     "%-15s : %d\n"  
  33.                     "%-15s : %s\n\n",  
  34.                     spider->blog->b_seq_num,  
  35.                     "title", spider->blog->b_title,  
  36.                     "url", spider->blog->b_url,  
  37.                     "date", spider->blog->b_date,  
  38.                     "reads", spider->blog->b_reads,  
  39.                     "comments", spider->blog->b_comments,  
  40.                     "download",   
  41.                     (spider->blog->b_download == BLOG_DOWNLOAD) ? "Download" : "UnDownload");  
  42.   
  43.         spider = spider->next;  
  44.     }  
  45.       
  46.     fclose(fp);  
  47. }  
  48. /********************************************************* 
  49. 将博客的基本信息打印到标准输出 
  50. *********************************************************/  
  51. static void print_rank(blog_rank *rank)  
  52. {  
  53.     char file[BUFSIZE] = {0};  
  54.     FILE *fp;  
  55.   
  56.     sprintf(file, "%s.log", csdn_id);  
  57.   
  58.     fp = fopen(file, "w+");  
  59.     if (NULL == fp) {  
  60.         #ifdef SPIDER_DEBUG  
  61.         fprintf(stderr, "fopen: %s\n", strerror(errno));  
  62.         #endif  
  63.         return;  
  64.     }  
  65.     setvbuf(stdout, NULL, _IONBF, 0);  
  66.       
  67.     fprintf(stdout, "优快云 ID : %s\n"  
  68.                     "TITLE   : %s\n"  
  69.                     "URL     : %s/%s\n"  
  70.                     "%s\n"  
  71.                     "%s\n"  
  72.                     "%s\n"  
  73.                     "%s\n"  
  74.                     "%s\n"  
  75.                     "%s\n"  
  76.                     "%s\n",  
  77.                     csdn_id,  
  78.                     rank->b_title,  
  79.                     优快云_BLOG_URL,  
  80.                     csdn_id,  
  81.                     rank->b_page_view,  
  82.                     rank->b_integral,  
  83.                     rank->b_ranking,  
  84.                     rank->b_original,  
  85.                     rank->b_reship,  
  86.                     rank->b_translation,  
  87.                     rank->b_comments);  
  88.   
  89.     fprintf(fp, "优快云 ID : %s\n"  
  90.                 "TITLE   : %s\n"  
  91.                 "URL     : %s/%s\n"  
  92.                 "%s\n"  
  93.                 "%s\n"  
  94.                 "%s\n"  
  95.                 "%s\n"  
  96.                 "%s\n"  
  97.                 "%s\n"  
  98.                 "%s\n",  
  99.                 csdn_id,  
  100.                 rank->b_title,  
  101.                 优快云_BLOG_URL,  
  102.                 csdn_id,  
  103.                 rank->b_page_view,  
  104.                 rank->b_integral,  
  105.                 rank->b_ranking,  
  106.                 rank->b_original,  
  107.                 rank->b_reship,  
  108.                 rank->b_translation,  
  109.                 rank->b_comments);  
  110.   
  111.     fclose(fp);  
  112. }  

唐僧:喂喂喂!大家不要生气,生气会犯了嗔戒的!悟空你也太调皮了,我跟你说过叫你不要乱扔东西,你怎么又…你看我还没说完你又把棍子给扔掉了!月光宝盒是宝物,你把他扔掉会污染花草草也是不对的! 

二.申请了空间,在程序结束后必须释放,要不内存泄露了,污染到内存,污染到花花草草也是不对的.

[cpp]  view plain copy
  1. /********************************************************* 
  2. 释放爬虫链表的空间 
  3. *********************************************************/  
  4. static void free_spider(blog_spider * spider_head)  
  5. {  
  6.     blog_spider *pspider;  
  7.     blog_spider *tmp;  
  8.   
  9.     pspider = spider_head;  
  10.       
  11.     while (pspider) {  
  12.         if (pspider->blog->b_url) {  
  13.             free(pspider->blog->b_url);  
  14.         }  
  15.         if (pspider->blog->b_host) {  
  16.             free(pspider->blog->b_host);  
  17.         }  
  18.         if (pspider->blog->b_page_file) {  
  19.             free(pspider->blog->b_page_file);  
  20.         }  
  21.         if (pspider->blog->b_local_file) {  
  22.             free(pspider->blog->b_local_file);  
  23.         }  
  24.         if (pspider->blog->b_title) {  
  25.             free(pspider->blog->b_title);  
  26.         }  
  27.         if (pspider->blog->b_date) {  
  28.             free(pspider->blog->b_date);  
  29.         }  
  30.           
  31.         free(pspider->blog);  
  32.   
  33.         tmp = pspider->next; /*保存下一个节点地址*/  
  34.         free(pspider);  
  35.         pspider = tmp;  
  36.     }  
  37. }  
  38.   
  39. /********************************************************* 
  40. 释放博客基本信息结构体空间 
  41. *********************************************************/  
  42. static void free_rank(blog_rank *rank)  
  43. {  
  44.     if (rank->b_title) {  
  45.         free(rank->b_title);  
  46.     }  
  47.     if (rank->b_page_view) {  
  48.         free(rank->b_page_view);  
  49.     }  
  50.     if (rank->b_integral) {  
  51.         free(rank->b_integral);  
  52.     }  
  53.     if (rank->b_ranking) {  
  54.         free(rank->b_ranking);  
  55.     }  
  56.     if (rank->b_original) {  
  57.         free(rank->b_original);  
  58.     }  
  59.     if (rank->b_reship) {  
  60.         free(rank->b_reship);  
  61.     }  
  62.     if (rank->b_translation) {  
  63.         free(rank->b_translation);  
  64.     }  
  65.     if (rank->b_comments) {  
  66.         free(rank->b_comments);  
  67.     }  
  68.       
  69.     free(rank);  
  70. }  

三.下载个人博客的主页,并分析出必要的信息,比如下载:http://blog.youkuaiyun.com/gzshun主页,程序将该文件保存到了本地的"index.html"文件中,先贴出一点html文件的源码,这样就更加清晰的了解代码的字符串解析:

博客标题:

[html]  view plain copy
  1. <div class="header">  
  2. <div id="blog_title">  
  3.     <h1>  
  4.         <a href="/gzshun">Open Linux C/C++专栏</a></h1>  
  5.     <h2></h2>  
  6.     <div class="clear">  
  7.     </div>  
  8. </div>  

博客的总页数:

[html]  view plain copy
  1. <!--显示分页-->  
  2. <div id="papelist" class="pagelist">  
  3. <span> 35条数据  共2页</span><strong>1</strong> <a href="/gzshun/article/list/2">2</a> <a href="/gzshun/article/list/2">下一页</a> <a href="/gzshun/article/list/2">尾页</a>   
  4. 只需要获取到"尾页"前面的数字即可.  

博客的排名,积分信息:

[html]  view plain copy
  1.   <span>gzshun</span>  
  2. </div>  
  3. <div id="blog_medal">  
  4. </div>  
  5. <ul id="blog_rank">  
  6.   <li>访问:<span>54524次</span></li>  
  7.   <li>积分:<span>1070分</span></li>  
  8.   <li>排名:<span>第5615名</span></li>  
  9. </ul>  
  10. <ul id="blog_statistics">  
  11.   <li>原创:<span>29篇</span></li>  
  12.   <li>转载:<span>6篇</span></li>  
  13.   <li>译文:<span>0篇</span></li>  
  14.   <li>评论:<span>209条</span></li>  
  15. </ul>  

贴出源码,这几个字符串解析函数没必要看,自己看下html的规则就能解析出来了:

[cpp]  view plain copy
  1. /********************************************************** 
  2. 获取博客的基本信息,包括以下几点(以下是按照页面的顺序, 
  3. 若不按照该顺序,每次查找必须重设偏移量到开头rewind(fp)): 
  4. 这里获取很多信息, 具体参考blog_spider与blog_rank结构体 
  5. **********************************************************/  
  6. static int get_blog_info(blog_spider * spider_head, blog_rank * rank)  
  7. {  
  8.     FILE *fp;  
  9.     int count;  
  10.     char *posA, *posB, *posC, *posD, *posE;  
  11.     char tmpbuf[BUFSIZE]   = {0};  
  12.     char tmpbuf2[BUFSIZE]  = {0};  
  13.     char line[BUFSIZE]     = {0};  
  14.     char *rank_info_addr[7];  
  15.       
  16.     fp = fopen(spider_head->blog->b_local_file, "r");  
  17.     if (NULL == fp) {  
  18.         fprintf(stderr, "fopen: %s\n", strerror(errno));  
  19.         return -1;  
  20.     }  
  21.   
  22.     /*查找博客的标题*/  
  23.     sprintf(tmpbuf, "<a href=\"/%s\">", csdn_id);  
  24.     while (fgets(line, sizeof(line), fp)) {  
  25.         posA = strstr(line, tmpbuf);  
  26.           
  27.         if (posA) {  
  28.             posA += strlen(tmpbuf);  
  29.             posB = strstr(posA, "</a>");  
  30.             *posB = 0;  
  31.             /*设置爬虫头结点的标题*/  
  32.             spider_head->blog->b_title = strdup(posA);  
  33.             rank->b_title = strdup(posA);  
  34.               
  35.             #ifdef SPIDER_DEBUG  
  36.             printf("%s\n", spider_head->blog->b_title);  
  37.             #endif  
  38.             break;  
  39.         }  
  40.     }  
  41.   
  42.     /*查找博客文章的总页数*/  
  43.     while (fgets(line, sizeof(line), fp)) {  
  44.         posA = strstr(line, HTML_MULPAGE);  
  45.           
  46.         if (posA) {  
  47.             fgets(line, sizeof(line), fp);  
  48.             posB = strrstr(line, BLOG_HREF);  
  49.   
  50.             /* /gzshun/article/list/N, N就是总页数 */  
  51.             memset(tmpbuf, 0, sizeof(tmpbuf));  
  52.             sprintf(tmpbuf, "/%s/%s/", csdn_id, BLOG_NEXT_LIST);  
  53.             posB += strlen(BLOG_HREF) + strlen(tmpbuf);  
  54.             posC = strchr(posB, '"');  
  55.             *posC = 0;  
  56.             rank->b_page_total = atoi(posB);  
  57.             spider_head->blog->b_seq_num = rank->b_page_total;  
  58.               
  59.             #ifdef SPIDER_DEBUG  
  60.             printf("b_page_total = %d\n", rank->b_page_total);  
  61.             #endif  
  62.               
  63.             break;  
  64.         }  
  65.     }  
  66.   
  67.     /*总共有7条信息: 访问 积分 排名 原创 转载 译文 评论*/  
  68.     while (fgets(line, sizeof(line), fp)) {  
  69.         posA = strstr(line, BLOG_RANK);  
  70.   
  71.         if (posA) {  
  72.             count = 0;  
  73.             while (fgets(line, sizeof(line), fp)) {  
  74.                 posB = strstr(line, BLOG_LI);  
  75.                 if (posB) {  
  76.                     if (7 == count) {  
  77.                         break;  
  78.                     }  
  79.                     posB += strlen(BLOG_LI);  
  80.                     posC = strstr(posB, BLOG_SPAN_HEAD);  
  81.                     posD = posC + strlen(BLOG_SPAN_HEAD);  
  82.                     posE = strstr(posD, BLOG_SPAN_END);  
  83.                     *posC = 0;  
  84.                     *posE = 0;  
  85.                     memset(tmpbuf, 0, sizeof(tmpbuf));  
  86.                     memset(tmpbuf2, 0, sizeof(tmpbuf2));  
  87.                     strcpy(tmpbuf, posB);  
  88.                     strcpy(tmpbuf2, posD);  
  89.                     strcat(tmpbuf, tmpbuf2);  
  90.                     rank_info_addr[count++] = strdup(tmpbuf);  
  91.                 }  
  92.             }  
  93.               
  94.             rank->b_page_view     = rank_info_addr[0];  
  95.             rank->b_integral      = rank_info_addr[1];  
  96.             rank->b_ranking       = rank_info_addr[2];  
  97.             rank->b_original      = rank_info_addr[3];  
  98.             rank->b_reship        = rank_info_addr[4];  
  99.             rank->b_translation   = rank_info_addr[5];  
  100.             rank->b_comments      = rank_info_addr[6];  
  101.               
  102.             break;  
  103.         }  
  104.     }  
  105.   
  106.     fclose(fp);  
  107.     return 0;  
  108. }  

以上使用了rank_info_addr数组,是为了在while (fgets(line, sizeof(line), fp)) 循环里面方便赋值。
博客里面可能有很多页,必须我的博客就有2页,这时候网址是这样:
http://blog.youkuaiyun.com/gzshun/article/list/1
http://blog.youkuaiyun.com/gzshun/article/list/2

所以循环下载blog.youkuaiyun.com对应自己的博客列表就行,网页文件的名称如:/gzshun/article/list/1 把gzshun改为自己的csdn的id就是了。

先来杯咖啡,待下一篇文章,前几天奔波在火车上,辛苦啊,今天及时赶到,马上发表,持之以恒。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值