中文字幕在线精品不卡_正在播放露脸一区_久久综合欧美_www.男人天堂

哈爾濱海月數據恢復,技術亞洲領先 設為首頁加入收藏RSS訂閱
中國區:哈爾濱(總部)鄭州福建深圳沈陽合肥大連包頭淄博上海廣州
    南京杭州嘉興武漢濟南青島新疆太原
亞太區:印度韓國泰國新加坡馬來西亞澳大利亞
Linux
Linux下網頁抓取

  來源:【51cto.com】

  ***近一直在學習stevens的unix網絡編程,對于網絡通信有了一定的認識,所以也想練練手。聊天程序之前用winsock做過,這次不想做重復的。之前看到一哥們寫過windows下抓取貓撲的帖子,我覺得抓頁面也是一個不錯想法。我也喜歡逛貓撲,有時候也去追追里面寫的文章,貓撲帖子少了一個很重要的功能,就是只看樓主的帖子。貓撲水人很多,容易把樓主的帖子淹沒在大海里面。

  查看了一下貓撲帖子的網頁源代碼,帖子內容介于

之間,只需要解析這段內容,就能得到自己想要的東西。不過里面東西比較多,比較雜,還是先找一個簡單頁面抓取試試。csdn博客相對來說就是個不錯的選擇,******沒廣告,內容不算很多,第二,代碼風格很好。抓CSDN的頁面無非獲得博主名,文章名字和URL等,如果想獲得更多的信息,可以把博主的排名,評論數抓取下來。

 

  自定義的結構體:

  [cpp] view plaincopyprint?

  struct BloggerInfo

  {

  int visits;//訪問次數

  int integral;//積分

  int ranking;//排名

  int artical_original;//原創文章數

  int artical_reproduce;//轉載文章數

  int artical_translation;//翻譯文章數

  int comments;//評論

  };

  struct ArticleInfo

  {

  char articleName[SMALLLEN];//文章標題

  char URL[SMALLLEN];//URL

  char createDate[25];//創建時間

  int visits;//訪問時間

  int comments;//評論次數

  struct ArticleInfo *next;//下一篇文章地址

  };

  struct Articles

  {

  int page;//頁數

  struct Articles * pageNext;//下一頁所在地址

  struct ArticleInfo *firstArticle;//該頁******篇文章地址

  struct ArticleInfo *currentArticle;//插入文章時使用,表示插入時的***后一篇文章

  };

  下面簡單分析一下CSDN博客源代碼。

  博主標題:

  [html] view plaincopyprint?

  


 

  


  編程小子的專欄

  

鍥而舍之,朽木不折;鍥而不舍,金石可鏤


  


  


  


  文章標題和URL:

  [html] view plaincopyprint?

  

  ubuntu11.10搭建git服務器

  

  文章訪問次數,評論次數等:

  [html] view plaincopyprint?

  


  

  閱讀(21)

  評論(0)

  


  博客統計信息:

  [html] view plaincopyprint?

  


     

      

  • 訪問:1218次

  •   

  • 積分:164分

  •   

  • 排名:千里之外

  •   


 

  [html] view plaincopyprint?

  


      

  • 原創:13篇

  •  

      

  • 轉載:2篇

  •   

  • 譯文:0篇

  •   

  • 評論:1條

  •   


  從上面貼出的HTML可以看出,所需要的信息都在某一個id下,每個id是******的,這對解析是很有利的。我們只需要抓取到網頁,分析相應內容,得到想要的信息即可。

  在確定CSDN博客是可以抓取后,就可以著手抓取。如何抓取?簡單來說,就是與CSDN博客服務器簡歷tcp連接,然后發送HTTP請求,得到響應。頁面抓取過程如下圖所示:

 

 

  主要流程:

  解析域名(csdn.blog.net),得到服務器IP地址

  與服務器端建立TCP連接

  發送HTTP請求

  得到服務器端響應,響應內容里面含有請求頁面源代碼

  解析網頁源代碼,得到所需要信息,如果需要抓取博主所有的文章,需要解析出每篇文章的URL

  統計博主文章數,判斷是否有分頁,如果又分頁,則請求分頁內容,獲取分頁的文章URL

  跳轉到******步,請求每篇文章

  把文章保存到本地

  根據需求看是否對文章進行處理

  知道流程后,就可以著手編碼。先來看看我目前作出來的效果圖。


 

 


 

  這里并不只是把文章信息解析出來,也把每篇博客具體內容給存到本地了。存在以博主名命名的文件夾下,每篇文章存在以文章命名的html文件中。

 

  具體實現:

  一、解析域名

  采用gethostbyname方法。函數聲明如下:

  [cpp] view plaincopyprint?

  #include

  struct hostent * gethostbyname(const char *hostname)

  執行成功,返回非空指針,失敗返回空指針,并設置h_errno,可以通過hstrerror方法查看h_errno對應的錯誤提示信息。

  函數中用到的hostent結構體,如下所示:

  [cpp] view plaincopyprint?

  

struct hostent
																												


  {

  char *h_name; /* 查詢主機的規范名字 */

  char **h_aliases; /* 別名 */

  int h_addrtype; /* 地址類型 */

  int h_length; /* 地址個數 */

  char **h_addr_list; /* 所有的地址 */

  };

  二、獲得IP地址后,與CSDN博客服務器建立TCP連接。

  解析域名和建立TCP鏈接,我都放在一個自定義函數buildconnect里面。每次需要建立連接,我只需要調用這個方法即可。代碼如下:

  [cpp] view plaincopyprint?

  /*

  *功能:獲得CSDN博客IP地址,并與CSDN服務器建立TCP連接

  *參數:無

  *返回值:非負描述字-成功,-1-出錯

  */

  int buildConnection() {

  int sockfd;

  static struct hostent *host = NULL;

  static struct sockaddr_in csdn_addr;

  if (host == NULL) {

  if ((host = gethostbyname(CSDN_BLOG_URL)) == NULL) {//獲取CSDN博客服務器IP地址

  fprintf(stderr, "gethostbyname error:%s\n", hstrerror(h_errno));

  exit(-1);

  }

  #ifdef DEBUG

  printf("csdn ip:%s\n", inet_ntoa(*((struct in_addr *) host->h_addr_list[0])));

  #endif

  bzero(&csdn_addr, sizeof (csdn_addr));

  csdn_addr.sin_family = AF_INET;

  csdn_addr.sin_port = htons(CSDN_BLOG_PORT);

  csdn_addr.sin_addr = *((struct in_addr *) host->h_addr_list[0]);

  }

  sockfd = socket(AF_INET, SOCK_STREAM, 0);

  if (sockfd == -1) {

  fprintf(stderr, "socked error:%s\n", strerror(errno));

  exit(-1);

  }

  if (connect(sockfd, (struct sockaddr *) &csdn_addr, sizeof (csdn_addr)) == -1) {

  fprintf(stderr, "connect error:%s", strerror(errno));

  exit(-1);

  }

  return sockfd;

  }

  不需要每一次都去解析域名,所以把域名存在一個static變量里面。

  三、發送HTTP請求

  HTTP請求格式如下所示:

  [cpp] view plaincopyprint?

  "GET /lanyan822 HTTP/1.1\r\n

  Accept:*/*\r\n

  Accept-Language:zh-cn\r\n

  User-Agent: Mozilla/4.0 (compatible;MSIE 5.01;Windows NT 5.0)\r\n

  Host: blog.csdn.net:80\r\n

  Connection: Close\r\n

  \r\n

  說明:GET:表明是一個GET請求,還有POST請求(你可以模擬登陸,發送用戶名和密碼到服務端。不過現在CSDN登陸需要一個隨機碼驗證。這個不好辦)/lanyan822表示請求的頁面,HTTP1.1表示使用的版本。\r\n表示結束。

  Accept:表示瀏覽器接受的MIME類型

  Accept-Language:表示瀏覽器接受的語言類型

  User-Agent:指瀏覽器的名字。呵呵,因為是模擬瀏覽器發請求,所以這里是假的

  Host:服務器的域名和端口

  Connection:用來告訴服務器是否可以維持固定的HTTP連接。HTTP/1.1使用Keep-Alive為默認值,這樣,當瀏覽器需要多個文件時(比如一個HTML文件和相關的圖形文件),不需要每次都建立連接。這里我每次請求頁面后,我都選擇關閉。

  這里需要注意的是:HTTP請求格式,千萬不能在里面多寫空格什么的。我之前一直請求頁面失敗就是因為里面多了空格。***后以\r\n結束。

  [cpp] view plaincopyprint?

  /*

  *功能:發送HTTP請求,HTTP請求格式一定要正確,且不能有多余的空格.

  *參數:sockfd:套接字,requestParam:http請求路徑

  *返回值:寫入套接口的字節數-成功,-1:失敗

  */

  int sendRequest(int sockfd, const char *requestParam) {

  char request[BUFFERLEN];

  int ret;

  bzero(request, sizeof (request));

  sprintf(request, "GET %s HTTP/1.1\r\n Accept:*/*\r\n Accept-Language:zh-cn\r\n"

  "User-Agent: Mozilla/4.0 (compatible;MSIE 5.01;Windows NT 5.0)\r\n"

  "Host: %s\r\n"

  "Connection: Close\r\n"

  "\r\n", requestParam, CSDN_BLOG_URL);

  #ifdef DEBUG

  printf("請求HTTP格式:%s\n", request);

  #endif

  ret = write(sockfd, request, sizeof (request));

  #ifdef DEBUG

  printf("send %d data to server\n", ret);

  #endif

  return ret;

  }

  四、接受服務端響應,并存儲請求頁面

  HTTP響應包括響應頭和所請求頁面的源代碼。

  HTTP響應頭如下所示:

  [cpp] view plaincopyprint?

  HTTP/1.1 200 OK

  Server: nginx/0.7.68

  Date: Wed, 16 May 2012 06:28:28 GMT

  Content-Type: text/html; charset=utf-8

  Connection: close

  Vary: Accept-Encoding

  X-Powered-By: ASP.NET

  Set-Cookie: uuid=344c2ad0-b060-448b-b75f-2c9dd308e5a5; expires=Thu, 17-May-2012 06:24:49 GMT; path=/

  Set-Cookie: avh=yKfd8EgMOqw1YuvAzcgrbQ%3d%3d; expires=Wed, 16-May-2012 06:29:49 GMT; path=/

  Cache-Control: private

  Content-Length: 18202

  響應頭部也是以\r\n結束。所以可以通過\r\n\r\n來判斷響應頭部的結束位置。

  實現源碼:

  [cpp] view plaincopyprint?

  /*

  *功能:將服務端返回的html內容存入filePath中.這里使用了select函數.

  *參數:sockfd:套接字,filePath:文件存儲路徑

  *返回值:讀入套接字字節數-成功,-1-失敗,-2請求頁面返回狀態值非200

  */

  int saveRequestHtml(int sockfd, const char *filePath) {

  int headerTag, ret, fileFd = -1,contentLen,count=0;

  char receiveBuf[BUFFERLEN];

  fd_set rset;

  struct timeval timeout;

  memset(&timeout, 0, sizeof (timeout));

  timeout.tv_sec = 60;

  timeout.tv_usec = 0;

  char *first, *last,*ok_loc,*pContentLenStart,*pContentLenEnd;

  while (TRUE) {

  FD_SET(sockfd, &rset);

  ret = select(sockfd + 1, &rset, NULL, NULL, &timeout);

  if (ret == 0) {

  fprintf(stderr, "select time out:%s\n", strerror(errno));

  return ret;

  } else

  if (ret == -1) {

  fprintf(stderr, "select error :%s\n", strerror(errno));

  return ret;

  }

  headerTag = 0;

  if (FD_ISSET(sockfd, &rset)) {

  while (ret = read(sockfd, receiveBuf, BUFFERLEN - 1)) {

  if (headerTag == 0) {

  if (access(filePath, F_OK) == 0) {

  if (remove(filePath) == -1)

  fprintf(stderr, "remove error:%s\n", strerror(errno));

  } else {

  #ifdef DEBUG

  printf("%s not exist\n", filePath);

  #endif

  }

  receiveBuf[ret] = '\0';

  first = strstr(receiveBuf, "\r\n\r\n");//服務端返回消息頭部和網頁html內容.消息頭部也是以\r\n\r\n結尾.

  if (first != 0) {

  last = first + strlen("\r\n\r\n");

  ok_loc=strstr(receiveBuf,"OK");//如果請求成功,狀態碼是200,并且有OK

  if(ok_loc!=0)

  {

  #ifdef DEBUG

  printf("頁面請求成功\n");

  #endif

  fileFd = open(filePath, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);

  if (fileFd == -1) {

  fprintf(stderr, "open error:%s\n", strerror(errno));

  return -1;

  }

  pContentLenStart=strstr(receiveBuf,CONTENT_LENGTH);//這里是為了獲取HTTP響應頭content-length大小。

  if(pContentLenStart!=0)

  {

  pContentLenEnd=strstr(pContentLenStart+strlen(CONTENT_LENGTH),"\r\n");

  if(pContentLenEnd!=0)

  {

  contentLen=myatoi(pContentLenStart,pContentLenEnd);

  #ifdef DEBUG

  printf("content-length:%d\n",contentLen);

  #endif

  count+= write(fileFd, last, ret - (last - receiveBuf));

  headerTag = 1;

  }else

  return -1;

  }else

  {

  return -1;

  }

  }else

  {

  return -2;//頁面請求失敗。

  }

  }

  #ifdef DEBUG

  printf("%s\n", receiveBuf);

  #endif

  } else {

  count+= write(fileFd, receiveBuf, ret);

  }

  }

  close(fileFd);

  }

  break;

  }

  if(count!=contentLen)

  {

  printf("接受長度與HTTP響應頭長度不一致\n");

  return -1;

  }

  return count;

  }

  五、解析網頁源代碼,得到所需要信息

  我主要解析了博客的文章名,文章URL,訪問次數,排名,積分,原創文章數,轉載文章數,翻譯文章數,評論數。

  源代碼解析是按照所需要的信息在源代碼中出現的順序依次解析,先出現文章名,接著是文章的評論,發表日期等信息,接著解析博主的積分,等級等,***后解析博主發表的文章數。

  解析用的***多的是strstr函數。

  [cpp] view plaincopyprint?

  #include

  char *strstr (char *haystack, const char *needle);

  函數功能:查找needle在haystack中******次出現的地址,查找成功,返回******次出現的地址,查找失敗返回0.類似于c++ string的find_first_of函數。

  信息解析出來,需要存儲下來。主要是存在自定義的數據結構里面。每一頁(***多50篇文章)存儲在struct Articles結構體里面,文章信息則存入struct ArticleInfo里面。頁面存儲結構如下圖所示:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
客戶服務 +more
上門服務
服務承諾
異地恢復
收費標準
付款方式
疑難解答
服務特色 +more
·免費檢測
·免費提供3天備份
·專業工程師提供服務
·免費清潔送修的介質
·數據恢復前報價,客戶確認后工程師開始數據恢復
·數據恢復不成功不收費
·與客戶簽訂保密協議,對客戶的數
 據嚴格保密,整個恢復過程不會對
 客戶的原盤有任何的寫操作,以確
 保原盤的數據完全

·免費參觀恢復全過程

·工程師在線免費咨詢

·專業工程師提供服務
服務器數據恢復 點擊這里給我發消

息
數據庫修復
點擊這里給我發

消息
硬盤數據恢復
點擊這里給我發消

息
中文字幕在线精品不卡_正在播放露脸一区_久久综合欧美_www.男人天堂

9000px;">

婷婷激情综合网| 精品国产免费久久| 亚洲gay无套男同| 日韩精品中文字幕在线不卡尤物| 欧美精选在线播放| 欧美群妇大交群中文字幕| 国产91富婆露脸刺激对白| 精品一区二区三区不卡| 三级精品在线观看| 亚洲欧美成人一区二区三区| 中文字幕中文在线不卡住| 久久日韩粉嫩一区二区三区| 日韩欧美美女一区二区三区| 欧美日韩和欧美的一区二区| 91视频91自| 91麻豆免费看| 国产欧美一区二区三区在线老狼| 亚洲色图视频网| 性感美女久久精品| 亚洲成av人片在www色猫咪| 亚洲视频中文字幕| 国产欧美日韩综合| 6080yy午夜一二三区久久| 欧美日韩在线观看一区二区 | 日韩国产在线观看一区| 一级女性全黄久久生活片免费| 中文无字幕一区二区三区 | 精品视频资源站| 欧美极品aⅴ影院| 国产精品进线69影院| 欧美一级搡bbbb搡bbbb| 久久综合久久综合亚洲| 欧美裸体一区二区三区| 欧美一区2区视频在线观看| 91免费观看国产| 在线欧美日韩国产| 91亚洲国产成人精品一区二区三| 久久99久久久欧美国产| 国产精一区二区三区| 日韩经典中文字幕一区| 国产成人鲁色资源国产91色综| 久久成人久久爱| 中文字幕在线一区| 欧美乱熟臀69xxxxxx| 亚洲欧美在线观看| 国产午夜一区二区三区| 成人欧美一区二区三区小说| 亚洲精品一区二区三区在线观看| 亚洲国产电影在线观看| 久久久无码精品亚洲日韩按摩| 亚洲欧洲美洲综合色网| 中文字幕中文乱码欧美一区二区| 成人app在线观看| 欧美吞精做爰啪啪高潮| 一本一本久久a久久精品综合麻豆| 777午夜精品免费视频| 欧美精品一卡两卡| 亚洲欧洲在线观看av| 亚洲一区二区三区三| 国产露脸91国语对白| 国产成人精品亚洲777人妖 | 欧美视频在线观看一区二区| 91成人国产精品| 久久不见久久见免费视频7| 欧美性感一类影片在线播放| 欧美日韩一区 二区 三区 久久精品| 国产亚洲视频系列| 国产精品日韩成人| 国产一区999| 99久久精品免费精品国产| 日韩精彩视频在线观看| 欧美性猛片xxxx免费看久爱| 在线不卡一区二区| 婷婷夜色潮精品综合在线| 九九国产精品视频| 日韩欧美一级二级三级| 国产精品久久久久久久第一福利 | 日本乱人伦一区| 91久久精品网| 亚洲特黄一级片| 蜜桃av一区二区| 欧美日本国产视频| 国产欧美日韩不卡| 国内精品伊人久久久久影院对白| 成人app在线观看| 中文字幕乱码亚洲精品一区 | 一个色在线综合| 亚洲天堂久久久久久久| 成人午夜看片网址| 欧美亚洲日本国产| 亚洲伦理在线精品| 奇米色一区二区| 这里只有精品电影| 亚洲免费观看视频| 国产在线一区二区| 中文一区在线播放| 日韩精品一二区| 欧美精品一区二区三| 亚洲高清免费在线| 欧美高清视频不卡网| 亚洲欧美日本在线| 91久久免费观看| 中文乱码免费一区二区| 91丨九色porny丨蝌蚪| 精品久久久久久亚洲综合网| 在线91免费看| 91精品在线观看入口| 精品成人a区在线观看| 91精品黄色片免费大全| 久久精品国产精品青草| 日本韩国欧美国产| 中文字幕不卡的av| 麻豆中文一区二区| 国产精品久99| 成人福利视频在线| 日韩中文欧美在线| 欧美性色黄大片手机版| 国产一区999| 久久久一区二区三区| 91在线视频免费91| 亚洲激情五月婷婷| 日韩欧美一区二区三区在线| 五月婷婷久久综合| 国产精品网曝门| 精品亚洲aⅴ乱码一区二区三区| 国产日产欧产精品推荐色| 日本丶国产丶欧美色综合| 国产精品99精品久久免费| 亚洲婷婷综合久久一本伊一区| 国产91精品一区二区麻豆亚洲| 亚洲欧洲日韩综合一区二区| 懂色av一区二区三区免费看| 国产一区二区三区免费| 午夜精品久久久久久久久久| 欧洲视频一区二区| 精品一区二区三区免费| 久久伊人蜜桃av一区二区| 亚洲天堂中文字幕| 精品国产91乱码一区二区三区| 免费人成在线不卡| 一二三四区精品视频| 欧美日韩三级一区二区| 波多野结衣中文字幕一区二区三区| 亚洲特级片在线| 国产色产综合色产在线视频| www.亚洲精品| 久久av资源站| 亚洲手机成人高清视频| 日本免费新一区视频| 国产成人午夜精品5599 | av电影在线观看完整版一区二区| 久久色中文字幕| 国产精品99久久久久久似苏梦涵| 婷婷综合五月天| 久久久久久久精| 精品国产伦一区二区三区观看体验 | 久久久精品天堂| 粉嫩高潮美女一区二区三区 | 亚洲摸摸操操av| 日本高清不卡在线观看| 粉嫩av一区二区三区粉嫩| 久久综合国产精品| 日韩一区二区在线看| 国产99久久久久| 国产揄拍国内精品对白| 亚洲天堂免费看| 成人网男人的天堂| 不卡影院免费观看| 一区2区3区在线看| 视频精品一区二区| 久久精品亚洲精品国产欧美| 2024国产精品| 欧美三级日韩三级| 欧美日韩情趣电影| 成人午夜电影网站| 97超碰欧美中文字幕| 麻豆91精品91久久久的内涵| 久草中文综合在线| 亚洲国产成人在线| 日韩色在线观看| 国产精品每日更新在线播放网址| 欧美精品一区二区三区在线播放 | 日韩激情视频在线观看| 亚洲激情自拍偷拍| 亚洲国产另类精品专区| 日韩电影在线一区| 国产精品一色哟哟哟| 国产福利一区二区三区| 成人一区二区三区在线观看| 白白色亚洲国产精品| 91丨porny丨户外露出| 欧美视频三区在线播放| 欧美一区二区三区公司| 日韩一区二区在线免费观看| 久久这里只有精品首页| 亚洲精品日韩一| 婷婷国产v国产偷v亚洲高清| 国产精品自拍在线| 九九精品一区二区| 99久免费精品视频在线观看|