閱讀803 返回首頁    go 阿裏雲 go 技術社區[雲棲]


自己動手編寫CSDN博客備份工具-blogspider

來源:https://blog.csdn.net/gzshun

  我之前一直在看lucene,nutch,發現有這麼一個現成的小應用,特轉來學習下!mark一下。


網絡爬蟲(又被稱為網頁蜘蛛,網絡機器人),是一種按照一定的規則,自動的抓取萬維網信息的程序或者腳本。另外一些不常使用的名字還有螞蟻,自動索引,模擬程序或者蠕蟲。


網絡爬蟲最重要的任務,就是從互聯網搜索出需要的信息,將網頁抓取下來並分析,很多搜索引擎,比如百度,穀歌,後台都有一隻很強悍的網絡爬蟲,用來訪問互聯網上的網頁,圖片,視頻等內容,並建立索引數據庫,使用戶能在百度搜索引擎中搜索到您網站的網頁、圖片、視頻等內容。

我們常見的幾個大型搜索引擎公司的爬蟲名稱:
1.穀歌(Google) -> Googlebot
2.百度(Baidu)爬蟲名稱:Baiduspider
3.雅虎(Yahoo) -> Yahoo! Slurp
4.有道(Yodao) -> YodaoBot
5.搜狗(sogou) -> Sogou spider
6.MSN -> msmbot
7.騰訊搜搜 -> Sosospider

最近我突然想自己動手寫一隻小型的博客爬蟲,將自己在CSDN博客網站寫的文章給抓取下來,想做個博客備份工具。當了解到網絡爬蟲的用途後,就來動手實現一個應用,用來備份自己在CSDN的博客,這樣即使沒有網絡,或者文章丟失了,我手頭都有一個備份。記得上次在微博看過CSDN創始人蔣濤先生說的一句話,他想做一個CSDN博客生成PDF文檔的工具,其實那也相當於對自己博客的備份,這樣就能很方便的瀏覽自己的寫的文章。

我寫的這個"blogspider"程序,將會把自己博客信息提取出來,並將所有的文章下載到本地。這裏隻是簡單的下載網頁而已,裏麵的圖片我沒有下載,那得涉及到太多的東西。如果電腦有網絡,將會很容易的看到博客裏麵的圖片,如果沒有網絡,圖片將無法顯示。

blogspider程序由C語言編寫的,基於Linux平台,我編寫該程序的環境如下:
[plain] view plaincopy
  1. gzshun@ubuntu:~$ uname -a  
  2. Linux ubuntu 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux  
  3. gzshun@ubuntu:~$ gcc -v  
  4. Using built-in specs.  
  5. Target: i486-linux-gnu  
  6. Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu  
  7. Thread model: posix  
  8. gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)  

本人在putty終端測試程序,可以正確的顯示中文,要設置為UTF-8,或者GB2312,如果顯示亂碼,切換一下字符集試試。


一.blogspider的功能簡介:

1.獲取博客的基本信息:
  博客標題
  博客訪問量
  博客積分
  博客排名
  博客原創文章數量
  博客轉載文章數量
  博客譯文文章數量
  博客評論數量

2.下載博客到本地:
  博客主題
  博客發表日期
  博客閱讀次數
  博客評論次數

二.blogspider涉及到的知識點:
1.文件I/O
2.網絡編程socket
3.數據結構-鏈表
4.內存分配


三.blogspider程序執行流程:
以我的博客為例:
1.將"https://blog.csdn.net/gzshun"主頁下載到本地
2.分析該主頁,獲取到博客的URL
3.將博客的URL添加到爬蟲鏈表
4.遍曆爬蟲鏈表,將博客下載到本地
5.將下載日誌保存在gzshun.log


四.blogspider程序的重要部分:

1.爬蟲鏈表的結構體

  1. typedef struct tag_blog_info {  
  2.     char *b_url;           /*網址*/  
  3.     char *b_host;          /*網站服務器主機名*/  
  4.     char *b_page_file;     /*頁麵文件名稱*/  
  5.     char *b_local_file;    /*本地保存的文件名稱*/  
  6.     char *b_title;         /*博客主題*/  
  7.     char *b_date;          /*博客發表日期*/  
  8.     int   b_port;          /*網址端口號*/  
  9.     int   b_sockfd;        /*網絡套接字*/  
  10.     int   b_reads;         /*閱讀次數*/  
  11.     int   b_comments;      /*評論次數*/  
  12.     int   b_download;      /*下載狀態*/  
  13.     int   b_lock;          /*處理鎖*/  
  14.     int   b_seq_num;       /*序號*/  
  15. }blog_info;  
  16.   
  17. typedef struct tag_blog_spider {  
  18.     blog_info *blog;  
  19.     struct tag_blog_spider *next;  
  20. }blog_spider;  

2.博客基本信息結構體
  1. typedef struct tag_blog_rank {  
  2.     int   b_page_total;    /*博客總頁數*/  
  3.     char *b_title;         /*博客標題*/  
  4.     char *b_page_view;     /*博客訪問量*/  
  5.     char *b_integral;      /*博客積分*/  
  6.     char *b_ranking;       /*博客排名*/  
  7.     char *b_original;      /*博客原創文章數量*/  
  8.     char *b_reship;        /*博客轉載文章數量*/  
  9.     char *b_translation;   /*博客譯文文章數量*/  
  10.     char *b_comments;      /*博客評論數量*/  
  11. }blog_rank;  

3.定義的函數
  1. static char *strrstr(const char *s1, const char *s2);  
  2. static char *strfchr(char *s);  
  3. static int  init_spider(blog_spider **spider);  
  4. static int  init_rank(blog_rank **rank);  
  5. static void insert_spider(blog_spider *spider_head, blog_spider *spider);  
  6. static int  spider_size(blog_spider *spider_head);  
  7. static void print_spider(blog_spider *spider_head);  
  8. static void print_rank(blog_rank *rank);  
  9. static void free_spider(blog_spider *spider_head);  
  10. static void free_rank(blog_rank *rank);  
  11. static int get_blog_info(blog_spider *spider_head, blog_rank *rank);  
  12. static int analyse_index(blog_spider *spider_head);  
  13. static int download_index(blog_spider *spider_head);  
  14. static int download_blog(blog_spider *spider);  
  15. static int get_web_host(const char *hostname);  
  16. static int connect_web(const blog_spider *spider);  
  17. static int send_request(const blog_spider * spider);  
  18. static int recv_response(const blog_spider * spider);  

4.strrstr是自己實現的,C庫沒有提供

1.strrstr函數:從一個字符串中查找指定字符串,返回最後一次出現的地址
程序如下:

  1. /************************************************************** 
  2. strrstr  : 查找指定字符串, 返回最後一次出現的地址, 自己實現 
  3. ***************************************************************/  
  4. static char *strrstr(const char *s1, const char *s2)  
  5. {  
  6.     int len2;  
  7.     char *ps1;  
  8.   
  9.     if (!(len2 = strlen(s2))) {  
  10.         return (char *)s1;  
  11.     }  
  12.       
  13.     ps1 = (char *)s1 + strlen(s1) - 1;  
  14.     ps1 = ps1 - len2 + 1;  
  15.   
  16.     while (ps1 >= s1) {  
  17.         if ((*ps1 == *s2) && (strncmp(ps1, s2, len2) == 0)) {  
  18.             return (char *)ps1;  
  19.         }  
  20.         ps1--;  
  21.     }  
  22.   
  23.     return NULL;  
  24. }  

5.初始化爬蟲鏈表
  1. /********************************************************* 
  2. 初始化博客爬蟲的鏈表節點, 申請空間並賦空值 
  3. *********************************************************/  
  4. static int init_spider(blog_spider * * spider)  
  5. {  
  6.     *spider = (blog_spider *)malloc(sizeof(blog_spider));  
  7.     if (NULL == *spider) {  
  8.         #ifdef SPIDER_DEBUG  
  9.         fprintf(stderr, "malloc: %s\n", strerror(errno));  
  10.         #endif  
  11.         return -1;  
  12.     }  
  13.   
  14.     (*spider)->blog = (blog_info *)malloc(sizeof(blog_info));  
  15.     if (NULL == (*spider)->blog) {  
  16.         #ifdef SPIDER_DEBUG  
  17.         fprintf(stderr, "malloc: %s\n", strerror(errno));  
  18.         #endif  
  19.         free(*spider);  
  20.         return -1;  
  21.     }  
  22.   
  23.     (*spider)->blog->b_url           = NULL;  
  24.     (*spider)->blog->b_host          = strdup(CSDN_BLOG_HOST);  
  25.     (*spider)->blog->b_page_file     = NULL;  
  26.     (*spider)->blog->b_local_file    = NULL;  
  27.     (*spider)->blog->b_title         = NULL;  
  28.     (*spider)->blog->b_date          = NULL;  
  29.     (*spider)->blog->b_port          = CSDN_BLOG_PORT;  
  30.     (*spider)->blog->b_sockfd        = 0;  
  31.     (*spider)->blog->b_reads         = 0;  
  32.     (*spider)->blog->b_comments      = 0;  
  33.     (*spider)->blog->b_download      = BLOG_UNDOWNLOAD;  
  34.     (*spider)->blog->b_lock          = BLOG_UNLOCK;  
  35.     (*spider)->blog->b_seq_num       = 0;  
  36.           
  37.     (*spider)->next = NULL;  
  38.   
  39.     return 0;  
  40. }  

6.初始化博客基本信息結構體
  1. /********************************************************* 
  2. 初始化博客基本信息結構體,包含以下幾個變量: 
  3. 1.博客頁麵總頁數 
  4. 2.博客標題 
  5. 3.博客訪問量 
  6. 4.博客積分 
  7. 5.博客排名 
  8. 6.博客原創文章數量 
  9. 7.博客轉載文章數量 
  10. 8.博客譯文文章數量 
  11. 9.博客評論數量 
  12. *********************************************************/  
  13. static int init_rank(blog_rank **rank)  
  14. {  
  15.     *rank = (blog_rank *)malloc(sizeof(blog_rank));  
  16.     if (NULL == *rank) {  
  17.         #ifdef SPIDER_DEBUG  
  18.         fprintf(stderr, "malloc: %s\n", strerror(errno));  
  19.         #endif  
  20.         return -1;  
  21.     }  
  22.   
  23.     (*rank)->b_page_total      = 0;  
  24.     (*rank)->b_title           = NULL;  
  25.     (*rank)->b_page_view       = NULL;  
  26.     (*rank)->b_integral        = NULL;  
  27.     (*rank)->b_ranking         = NULL;  
  28.     (*rank)->b_original        = NULL;  
  29.     (*rank)->b_reship          = NULL;  
  30.     (*rank)->b_translation     = NULL;  
  31.     (*rank)->b_comments        = NULL;  
  32.   
  33.     return 0;  
  34. }  

五.blogspider遇到的問題:
1.博客標題如果有'/','?',或者其他不規則的符號,文件將會創建失敗。
  解決方案:將不規則的符號賦空,並在後麵連接"xxx"字符串,表示省略;
2.在接受網站服務器響應的時候,要將select函數的時間設置長點,有時候因為網絡差的問題,將會超時導致退出程序。在blogspider裏麵,將timeout設置30s。
3.本程序在考慮加入多線程遍曆爬蟲鏈表,經過嚐試,連接網站服務器會出現競爭問題,將導致連接延時,影響程序效率,暫時不考慮。

六.blogspider運行截圖:




使用blogspider:

這裏以下載我的博客為例,我CSDN的ID是:gzshun, 網址是:https://blog.csdn.net/gzshun





title              : 博客標題

url                : 博客網址

date            : 博客發表日期

reads          : 博客閱讀次數

comments  : 博客評論次數

download   : 博客下載狀態


以下這張圖片是在windows查看的,通過samba連接到ubuntu服務器。我博客上麵的所有文章已經成功地下載到本地。


打開下載在本地的html文件,此時有網絡。

打開下載在本地的html文件,此時無網絡。



若需要blogspider的源程序,請留下您的E-mail(注意要寫成我後麵的那種形式,否則會被非法網絡爬蟲抓取),或者直接聯係我的E-mail:gzshuns#163.com (#->@).


前一篇博文《自己動手編寫CSDN博客備份工具-blogspider》介紹了blogspider的使用,使用方法很簡單,blogspider可以將自己的CSDN博客下載到本地,這裏也隻提供最基本的功能。這兩天有很多哥們兒給我發郵件,想要blogspider的源碼,該程序是開源的,有需要的可以留下聯係方式。
今天就介紹下blogspider的源代碼,其實這裏麵比較核心的東西就是如何向網站服務器申請我們需要的網頁文件。在Java語言,有提供一些網絡包,已經將HTTP協議的東西都集成在了包裏麵,那實現起來就比較簡單。最近由於春運期間,大家都在12306網站購票,於是網上就出現了一款搶票的軟件,那是用Java寫的,是一個穀歌插件。其實那個軟件是我一個同事以前的同事寫出來的,我們都從這裏受益,也買到了回家過年的票,在這裏感謝那位牛人。
向Java程序員了解了一下,那個軟件的實現原理很簡單,步驟如下:
1.訪問網站獲取網站信息
2.接受到網站服務器的響應消息
3.根據用戶選擇(硬座,硬臥)的消息再提交到網站服務器
4.得到網站的結果

主要是2個操作:一個是GET方法,一個是POST方法。
GET方法: 從網站服務器下載網頁消息,比如網頁瀏覽器可以瀏覽CSDN網站的新聞與圖片,這些都是從網站服務器GET下載到本地;
POST方法:從本地將資料提交到網站服務器,比如在CSDN博客寫完文章要點擊發表博客,這時候是將一篇文章的所有信息給POST到CSDN服務器。
blogspider的主要目的,就是下載功能,這裏使用的是GET方法,用C語言寫的都比較低級,這些最基本的都需要自己來實現,等有空看看麵向對象編程語言的實現。

廢話少說,源碼說話:

一.貼出代碼中的調試宏,汗,太兒戲了

  1. /*Debug program macro*/  
  2. #if 0  
  3. #define SPIDER_DEBUG  
  4. #endif  

二.貼出代碼中的一些宏定義,這些涉及到HTML文件的語法,但本代碼不需要會html,隻需要最基本的字符串處理:

  1. #define BUFSIZE          1024  
  2.   
  3. #define HTML_ARTICLE     ("<span class=\"link_title\">")  
  4. #define HTML_MULPAGE     ("class=\"pagelist\"")  
  5. #define BLOG_NEXT_LIST   ("article/list")  
  6. #define BLOG_TITLE       ("title=\"")  
  7. #define BLOG_HREF        ("<a href=\"")  
  8. #define BLOG_DATE        ("<span class=\"link_postdate\">")  
  9. #define BLOG_READ        ("<span class=\"link_view\"")  
  10. #define BLOG_COMMENT     ("<span class=\"link_comments\"")  
  11. #define BLOG_SPAN_HEAD   ("<span>")  
  12. #define BLOG_SPAN_END    ("</span>")  
  13. #define BLOG_RANK        ("blog_rank")  
  14. #define BLOG_LI          ("<li>")  
  15. #define BLOG_INDEX       ("index.html")  
  16. #define CSDN_BLOG_URL    ("https://blog.csdn.net")  
  17. #define CSDN_BLOG_HOST   ("blog.csdn.net")  
  18. #define CSDN_BLOG_PORT   (80)  
  19.   
  20. #define BLOG_LOCK        (10)  
  21. #define BLOG_UNLOCK      (11)  
  22. #define BLOG_DOWNLOAD    (20)  
  23. #define BLOG_UNDOWNLOAD  (21)  

上麵的BLOG_LOCK,BLOG_UNLOCK是爬蟲鏈表的處理鎖,這是擴展預留的,現在還沒用。本來要用多線程來處理鏈表,但經過測試,會產生競爭,導致connect超時,這等過完年再試試。

三.這裏再給出爬蟲鏈表的結構體與博客存放基本信息的結構體,裏麵有多一些變量,但沒真正的使用,有些隻是預留而已:

  1. typedef struct tag_blog_info {  
  2.     char *b_url;           /*網址*/  
  3.     char *b_host;          /*網站服務器主機名*/  
  4.     char *b_page_file;     /*頁麵文件名稱*/  
  5.     char *b_local_file;    /*本地保存的文件名稱*/  
  6.     char *b_title;         /*博客主題*/  
  7.     char *b_date;          /*博客發表日期*/  
  8.     int   b_port;          /*網址端口號*/  
  9.     int   b_sockfd;        /*網絡套接字*/  
  10.     int   b_reads;         /*閱讀次數*/  
  11.     int   b_comments;      /*評論次數*/  
  12.     int   b_download;      /*下載狀態*/  
  13.     int   b_lock;          /*處理鎖*/  
  14.     int   b_seq_num;       /*序號*/  
  15. }blog_info;  
  16.   
  17. typedef struct tag_blog_spider {  
  18.     blog_info *blog;  
  19.     struct tag_blog_spider *next;  
  20. }blog_spider;  
  21.   
  22. typedef struct tag_blog_rank {  
  23.     int   b_page_total;    /*博客總頁數*/  
  24.     char *b_title;         /*博客標題*/  
  25.     char *b_page_view;     /*博客訪問量*/  
  26.     char *b_integral;      /*博客積分*/  
  27.     char *b_ranking;       /*博客排名*/  
  28.     char *b_original;      /*博客原創文章數量*/  
  29.     char *b_reship;        /*博客轉載文章數量*/  
  30.     char *b_translation;   /*博客譯文文章數量*/  
  31.     char *b_comments;      /*博客評論數量*/  
  32. }blog_rank;  

四.在一個程序中,使用全局變量不是最好的方法,但都有優缺點:

使用全局變量:
1.優點:操作簡單,不用提供太多的函數形參;
2.缺點:不好維護,代碼可讀性差;所以該程序隻使用了3個全局變量。

  1. /*global variable*/  
  2. static int g_seq_num = 0;  
  3. static char csdn_id[255];  
  4. static struct hostent *web_host;  

web_host變量用來保存"blog.csdn.net"主機信息,在初始化socket的使用會使用到裏麵的IP地址, web_host->h_addr_list[0];

五.程序中定義了很多函數,如下:

  1. static char *strrstr(const char *s1, const char *s2);//從s1字符串中查找s2字符串,返回最後一次出現的地址  
  2. static char *strfchr(char *s);//過濾掉s字符串中不規則的字符  
  3. static int  init_spider(blog_spider **spider);//初始化博客爬蟲節點,必須使用指針的指針,否則達不到預期效果  
  4. static int  init_rank(blog_rank **rank);//初始化博客存放基本信息的結構體  
  5. static void insert_spider(blog_spider *spider_head, blog_spider *spider);//將博客插入爬蟲鏈表  
  6. static int  spider_size(blog_spider *spider_head);//計算爬蟲鏈表的長度  
  7. static void print_spider(blog_spider *spider_head);//打印爬蟲鏈表,保存到當前目錄的*.log文件  
  8. static void print_rank(blog_rank *rank);//打印博客基本信息  
  9. static void free_spider(blog_spider *spider_head);//釋放爬蟲鏈表的空間  
  10. static void free_rank(blog_rank *rank);//釋放博客基本信息的空間  
  11. static int get_blog_info(blog_spider *spider_head, blog_rank *rank);//從博客主頁獲取博客標題,博客文章的總頁數,積分,排名等信息  
  12. static int analyse_index(blog_spider *spider_head);分析每一頁博客的信息,並添加進爬蟲鏈表  
  13. static int download_index(blog_spider *spider_head);//下載博客主頁  
  14. static int download_blog(blog_spider *spider);//下載每一篇博客  
  15. static int get_web_host(const char *hostname);//得到"blog.csdn.net"網站的主機信息  
  16. static int connect_web(const blog_spider *spider);//初始化socket,並連接網站服務器  
  17. static int send_request(const blog_spider * spider);//給網站服務器發送請求  
  18. static int recv_response(const blog_spider * spider);//接受網站服務器的響應消息  

六.先給出上述2個字符串處理函數,這家夥,有點羅嗦
  1. /************************************************************** 
  2. strrstr  : 查找指定字符串, 返回最後一次出現的地址, 自己實現 
  3. ***************************************************************/  
  4. static char *strrstr(const char *s1, const char *s2)  
  5. {  
  6.     int len2;  
  7.     char *ps1;  
  8.   
  9.     if (!(len2 = strlen(s2))) {  
  10.         return (char *)s1;  
  11.     }  
  12.       
  13.     ps1 = (char *)s1 + strlen(s1) - 1;  
  14.     ps1 = ps1 - len2 + 1;  
  15.   
  16.     while (ps1 >= s1) {  
  17.         if ((*ps1 == *s2) && (strncmp(ps1, s2, len2) == 0)) {  
  18.             return (char *)ps1;  
  19.         }  
  20.         ps1--;  
  21.     }  
  22.   
  23.     return NULL;  
  24. }  
  25.   
  26. /********************************************************* 
  27. strfchr  : 查找指定字符串中不規則的字符, 並賦空 
  28. 若沒有刪除這些不規則的字符,則創建文件的時候將會出錯 
  29. *********************************************************/  
  30. static char *strfchr(char *s)  
  31. {  
  32.     char *p = s;  
  33.       
  34.     while (*p) {  
  35.         if (('/' == *p) || ('?' == *p)) {  
  36.             *p = 0;  
  37.             strcat(s, "xxx");  
  38.               
  39.             return p;  
  40.         }  
  41.         p++;  
  42.     }  
  43.       
  44.     return NULL;  
  45. }  

引用星爺的一句話:"功夫其實絕對是適合男女老幼的,打打殺殺隻是大家對它的誤解。功夫更加是一種藝術,一種不屈的精神。所以,一直以來我都在找方法想將功夫重新包裝起來,使得你們這些升鬥小民對功夫能夠有更深一層的了解。".
輕鬆一下,繼續:

七.初始化爬蟲鏈表,我把很多處理都給獨立到函數了,這樣可以增加程序的可讀性,不能將所有功能都在main函數實現.

  1. /********************************************************* 
  2. 初始化博客爬蟲的鏈表節點, 申請空間並賦空值 
  3. *********************************************************/  
  4. static int init_spider(blog_spider * * spider)  
  5. {  
  6.     *spider = (blog_spider *)malloc(sizeof(blog_spider));  
  7.     if (NULL == *spider) {  
  8.         #ifdef SPIDER_DEBUG  
  9.         fprintf(stderr, "malloc: %s\n", strerror(errno));  
  10.         #endif  
  11.         return -1;  
  12.     }  
  13.   
  14.     (*spider)->blog = (blog_info *)malloc(sizeof(blog_info));  
  15.     if (NULL == (*spider)->blog) {  
  16.         #ifdef SPIDER_DEBUG  
  17.         fprintf(stderr, "malloc: %s\n", strerror(errno));  
  18.         #endif  
  19.         free(*spider);  
  20.         return -1;  
  21.     }  
  22.   
  23.     (*spider)->blog->b_url           = NULL;  
  24.     (*spider)->blog->b_host          = strdup(CSDN_BLOG_HOST);  
  25.     (*spider)->blog->b_page_file     = NULL;  
  26.     (*spider)->blog->b_local_file    = NULL;  
  27.     (*spider)->blog->b_title         = NULL;  
  28.     (*spider)->blog->b_date          = NULL;  
  29.     (*spider)->blog->b_port          = CSDN_BLOG_PORT;  
  30.     (*spider)->blog->b_sockfd        = 0;  
  31.     (*spider)->blog->b_reads         = 0;  
  32.     (*spider)->blog->b_comments      = 0;  
  33.     (*spider)->blog->b_download      = BLOG_UNDOWNLOAD;  
  34.     (*spider)->blog->b_lock          = BLOG_UNLOCK;  
  35.     (*spider)->blog->b_seq_num       = 0;  
  36.           
  37.     (*spider)->next = NULL;  
  38.   
  39.     return 0;  
  40. }  
  41.   
  42. /********************************************************* 
  43. 初始化博客基本信息結構體,包含以下幾個變量: 
  44. 1.博客頁麵總頁數 
  45. 2.博客標題 
  46. 3.博客訪問量 
  47. 4.博客積分 
  48. 5.博客排名 
  49. 6.博客原創文章數量 
  50. 7.博客轉載文章數量 
  51. 8.博客譯文文章數量 
  52. 9.博客評論數量 
  53. *********************************************************/  
  54. static int init_rank(blog_rank **rank)  
  55. {  
  56.     *rank = (blog_rank *)malloc(sizeof(blog_rank));  
  57.     if (NULL == *rank) {  
  58.         #ifdef SPIDER_DEBUG  
  59.         fprintf(stderr, "malloc: %s\n", strerror(errno));  
  60.         #endif  
  61.         return -1;  
  62.     }  
  63.   
  64.     (*rank)->b_page_total      = 0;  
  65.     (*rank)->b_title           = NULL;  
  66.     (*rank)->b_page_view       = NULL;  
  67.     (*rank)->b_integral        = NULL;  
  68.     (*rank)->b_ranking         = NULL;  
  69.     (*rank)->b_original        = NULL;  
  70.     (*rank)->b_reship          = NULL;  
  71.     (*rank)->b_translation     = NULL;  
  72.     (*rank)->b_comments        = NULL;  
  73.   
  74.     return 0;  
  75. }  

八.爬蟲鏈表的一些處理,這些都比較簡單,就都貼出來吧
  1. /********************************************************* 
  2. 將博客爬蟲節點插入爬蟲鏈表 
  3. *********************************************************/  
  4. static void insert_spider(blog_spider * spider_head, blog_spider * spider)  
  5. {  
  6.     blog_spider *pspider;  
  7.   
  8.     pspider = spider_head;  
  9.   
  10.     while (pspider->next) {  
  11.         pspider = pspider->next;  
  12.     }  
  13.       
  14.     pspider->next = spider;  
  15. }  
  16.   
  17. /********************************************************* 
  18. 返回爬蟲鏈表長度 
  19. *********************************************************/  
  20. static int spider_size(blog_spider * spider_head)  
  21. {  
  22.     int count = 0;  
  23.     blog_spider *pspider;  
  24.   
  25.     pspider = spider_head;  
  26.   
  27.     while (pspider->next) {  
  28.         pspider = pspider->next;  
  29.         count++;  
  30.     }  
  31.       
  32.     return count;  
  33. }  

篇幅有點長,待下篇文章...
周星馳:你來這裏幹什麼?
趙薇:我想幫你們比賽。
周星馳:你怎麼幫?你快點回火星吧,地球是很危險的。


唐僧:你想要啊?悟空,你要是想要的話你就說話嘛,你不說我怎麼知道你想要呢,雖然你很有誠意地看著我,可是你還是要跟我說你想要的。你真的想要嗎?那你就拿去吧!你不是真的想要吧?難道你真的想要嗎?…… 
悟空:我Kao!


在開篇,先happy下,有個好心情,才能天天向上,奮發圖強,自強不息。

繼《自己動手編寫CSDN博客備份工具-blogspider》與《自己動手編寫CSDN博客備份工具-blogspider之源碼分析(1)》博文後,繼續貼出處理的一些函數,原理很簡單。

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

  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, "CSDN 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.                     CSDN_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,   最後更新:2017-04-03 20:57:46

      上一篇:go 各大網站收錄入口| 各大搜索引擎提交 | 搜索引擎提交地址
      下一篇:go iPhone上安裝Android係統詳細步驟