當前位置:首頁 » 編程語言 » c語言dom節點
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言dom節點

發布時間: 2022-12-09 23:37:22

c語言如何向網站提交信息(有沒有像html的get的提交方式)最好給個例子

之前使用過PHP的Simple HTML DOM簡單地解析HTML但PHP終非我所熟悉的語言,雖然我並不對語言抱有絕對的執著= =(什麼你不相信,好吧,不管你信不信,反正我是信了= =)。雖然可以簡單地使用正則表達式來解析HTML但我不是希望能夠找到一個合適的HTML解析庫,網上搜索了下關於c語言解析HTML的庫,好像不是挻多的樣子,我搜索到了google的gumbo,
gumbo是開源的,可以從這里得到它
https://github.com/google/gumbo-parser
我們需要下載回來手動編譯安裝,這里以linux debian為例
git clone https://github.com/google/gumbo-parser
cd gumbo-parser
./autogen.sh
./configure
這些一般都會非常順利,沒什麼好說的,接下來就是
make
我要執行make後發現有一個錯誤導致無法編譯通過,不知道各位是什麼情況,給出的錯誤提示是benchmarks/benchmark.cc
文件中使用了未定義的函數clock_gettime
man了一下,該函數需要包含time.h頭文件,打開benchmark.cc文件查看的確已經包含了time.h頭文件,很苦惱,突然一下子就懵了,不過還好我反應還算快,看到manpages中寫到
Link with -lrt (only for glibc versions before 2.17).
於是猜測沒有鏈接庫,使用vim打開Makefile文件,這個文件內容太多= =,要分析的話有些費勁,不過機智的我還是很快地通過benchmark關鍵字定位到了benchmark_LDADD這個變數,然後在後面加上
-lrt
注意有空格
再次make,果然成功了。。。。。。。。。。。
編譯完成之後就可以使用make install進行安裝了,你可能需要使用root用戶許可權,因為默認的安裝目錄在/usr/local/下
gumbo的源碼提供了幾個示常式序,一個c語言寫的獲取標題的源碼和另外三個使用c++編寫的代碼,我全都看了(你看,我說過我不是絕對的語言執著者吧,很不幸,這些程序我都看懂了= =)
簡單地說gumbo的使用很簡單,使用gumbo_parse或者gumbo_parse_with_options就可以得到一個GumboOutput數據結構,我們就可以從該結構中尋找我們想要的東西了。
我們先來看一個簡單的例子,就拿獲取title來說吧,我決定用自己寫的解析代碼而不是gumbo源碼提供的好個示例,因為我發現該程序無法解析出我使用的示例HTML文本文件= =,所以我就自己寫個吧。。。。。。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
/* 包含頭文件 */
#include <gumbo.h>

void get_title(GumboNode *node)
{
GumboVector *children;
int i;

/* 如果當前節點不是一個元素的話直接返回 */
if(node->type != GUMBO_NODE_ELEMENT) return;
/* 獲取該節點的所有子元素節點 */
children=&node->v.element.children;

/* 檢查當前節點的標簽是否為TITLE(title)
* 如果是則輸出該節點下第一個節點的文本內容 */
if(node->v.element.tag == GUMBO_TAG_TITLE)
printf("%s\n",((GumboNode *)children->data[0])->v.text.text);

/* 遞歸該節點下的所有子節點 */
for(i=0;i < children->length;++i)
get_title(children->data[i]);
}

int main(int argc,char **argv)
{
struct stat buf;
GumboOutput *output;
FILE *fp;
char *data;

/* 讀取HTML文本文件 */
if(!(fp=fopen(argv[1],"rb"))) return -1;
stat(argv[1],&buf);
data=malloc(sizeof(char)*(buf.st_size+1));
fread(data,sizeof(char),buf.st_size,fp);
fclose(fp);
data[buf.st_size]=0;

/* 解析HTML文本文件 */
output=gumbo_parse(data);
/* 獲取TITLE */
get_title(output->root);

/* 銷毀,釋放內存 */
gumbo_destroy_output(&kGumboDefaultOptions,output);
free(data);

return 0;
}
注釋已經寫的很清楚了,首先我們的節奏是這個樣子的:
第一步載入HTML文本文件,我們把它讀到一個buf中,
第二步我們進行解析出GumboOutput數據結構
第三步在GumboOptout這個數據結構中找出title標簽
最後我們輸出內容,gumbo的步驟基本上就是這個樣子的了,使用gcc編譯的時候需要加上
-lgumbo
下面再說一個例子,該例子中的HTML文件內容是各國DNS的IP地址以及物理地址,大概的格式是
<dt><dd class="ipstart">開始ip地址</dd><dd class="ipend">結束ip地址</dd><dd class="address">物理地址</dd></dt>
我們的解析步驟是獲取所有dt標簽再獲取所有dd標簽,然後分別輸出dd標簽中class屬性為ipstart、ipend、address的內 容,下面放代碼,由於原HTML文本文件內容放多,我不便放上來,這里就使用在線抓取的方式獲取HTML文本,所以這里給出的是HTML文本的url地 址,至目前寫代碼這一刻該程序還是完全能夠正常工作的,日後會該網頁是否會因該網頁做調整等原因解析出錯就不得而知了。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <oauth.h>
/* 包含頭文件 */
#include <gumbo.h>

#define URL "http://ip.yqie.com/dns_usa.htm"

void print_dns(GumboNode *node,GumboAttribute *attr)
{
/* 獲取子節點 */
GumboNode *ip=(GumboNode *)(&node->v.element.children)->data[0];

/* 根據class屬性的值列印結果 */
if(strcmp(attr->value,"ipstart") == 0)
{
if(ip->type == GUMBO_NODE_TEXT)
printf("開始IP:%s ",ip->v.text.text);
}
else if(strcmp(attr->value,"ipend") == 0)
{
if(ip->type == GUMBO_NODE_TEXT)
printf("結束IP:%s ",ip->v.text.text);
}
else if(strcmp(attr->value,"address") == 0)
{
if(ip->type == GUMBO_NODE_TEXT)
printf("物理地址:%s\n",ip->v.text.text);
}
}

void get_dns(GumboNode *node,GumboTag tag)
{
GumboVector *children;
GumboAttribute *attr;
int i;

if(node->type != GUMBO_NODE_ELEMENT) return;
/* 獲取當前節點class屬性 */
if(attr=gumbo_get_attribute(&node->v.element.attributes,"class"))
print_dns(node,attr);

/* 當前節點子節點 */
children=&node->v.element.children;
/* 如果當前節點標簽為td我們就查找dd標簽 */
if(node->v.element.tag == GUMBO_TAG_DT)
for(i=0;i < children->length;++i)
get_dns(children->data[i],GUMBO_TAG_DD);

/* 查找所有<dt>標簽 */
for(i=0;i < children->length;++i)
get_dns(children->data[i],GUMBO_TAG_DT);
}

int main(void)
{
GumboOutput *output;
char *buf;

/* 下載HTML文本文件 */
buf=oauth_http_get(URL,NULL);
if(!buf) return-1;
/* 解析 */
output=gumbo_parse(buf);
if(!output)
{
free(buf);
return -1;
}
/* 獲取我們想要的內容 <dt>*/
get_dns(output->root,GUMBO_TAG_DT);

/* 釋放資源 */
gumbo_destroy_output(&kGumboDefaultOptions,output);
free(buf);

return 0;
}