1. 之前使用过PHPSimple HTML DOM简单地解析HTMLPHP终非我所熟悉的语言,虽然我并不对语言抱有绝对的执着= =(什么你不相信,好吧,不管你信不信,反正我是信了= =)。虽然可以简单地使用正则表达式来解析HTML但我不是希望能够找到一个合适的HTML解析库,网上搜索了下关于c语言解析HTML的库,好像不是挻多的样子,我搜索到了googlegumbo
  2.  
  3. gumbo是开源的,可以从这里得到它
  4.  
  5. https://github.com/google/gumbo-parser
  6.  
  7. 我们需要下载回来手动编译安装,这里以linux debian为例
  8.  
  9. git clone https://github.com/google/gumbo-parser
  10. cd gumbo-parser
  11. ./autogen.sh
  12. ./configure
  13.  
  14. 这些一般都会非常顺利,没什么好说的,接下来就是
  15. make
  16. 我要执行make后发现有一个错误导致无法编译通过,不知道各位是什么情况,给出的错误提示是benchmarks/benchmark.cc
  17. 文件中使用了未定义的函数clock_gettime
  18. man了一下,该函数需要包含time.h头文件,打开benchmark.cc文件查看的确已经包含了time.h头文件,很苦恼,突然一下子就懵了,不过还好我反应还算快,看到manpages中写到
  19. Link with -lrt (only for glibc versions before 2.17).
  20. 于是猜测没有链接库,使用vim打开Makefile文件,这个文件内容太多= =,要分析的话有些费劲,不过机智的我还是很快地通过benchmark关键字定位到了benchmark_LDADD这个变量,然后在后面加上
  21. -lrt
  22. 注意有空格
  23. 再次make,果然成功了。。。。。。。。。。。
  24. 编译完成之后就可以使用make install进行安装了,你可能需要使用root用户权限,因为默认的安装目录在/usr/local/下
  25.  
  26. gumbo的源码提供了几个示例程序,一个c语言写的获取标题的源码和另外三个使用c++编写的代码,我全都看了(你看,我说过我不是绝对的语言执着者吧,很不幸,这些程序我都看懂了= =)
  27.  
  28. 简单地说gumbo的使用很简单,使用gumbo_parse或者gumbo_parse_with_options就可以得到一个GumboOutput数据结构,我们就可以从该结构中寻找我们想要的东西了。
  29. 我们先来看一个简单的例子,就拿获取title来说吧,我决定用自己写的解析代码而不是gumbo源码提供的好个示例,因为我发现该程序无法解析出我使用的示例HTML文本文件= =,所以我就自己写个吧。。。。。。
  30.  
  31. #include <stdio.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. /* 包含头文件 */
  37. #include <gumbo.h>
  38.  
  39. void get_title(GumboNode *node)
  40. {
  41. GumboVector *children;
  42. int i;
  43.  
  44. /* 如果当前节点不是一个元素的话直接返回 */
  45. if(node->type != GUMBO_NODE_ELEMENT) return;
  46. /* 获取该节点的所有子元素节点 */
  47. children=&node->v.element.children;
  48.  
  49. /* 检查当前节点的标签是否为TITLE(title)
  50. * 如果是则输出该节点下第一个节点的文本内容 */
  51. if(node->v.element.tag == GUMBO_TAG_TITLE)
  52. printf("%s\n",((GumboNode *)children->data[])->v.text.text);
  53.  
  54. /* 递归该节点下的所有子节点 */
  55. for(i=;i < children->length;++i)
  56. get_title(children->data[i]);
  57. }
  58.  
  59. int main(int argc,char **argv)
  60. {
  61. struct stat buf;
  62. GumboOutput *output;
  63. FILE *fp;
  64. char *data;
  65.  
  66. /* 读取HTML文本文件 */
  67. if(!(fp=fopen(argv[],"rb"))) return -;
  68. stat(argv[],&buf);
  69. data=malloc(sizeof(char)*(buf.st_size+));
  70. fread(data,sizeof(char),buf.st_size,fp);
  71. fclose(fp);
  72. data[buf.st_size]=;
  73.  
  74. /* 解析HTML文本文件 */
  75. output=gumbo_parse(data);
  76. /* 获取TITLE */
  77. get_title(output->root);
  78.  
  79. /* 销毁,释放内存 */
  80. gumbo_destroy_output(&kGumboDefaultOptions,output);
  81. free(data);
  82.  
  83. return ;
  84. }
  85. 注释已经写的很清楚了,首先我们的节奏是这个样子的:
  86. 第一步加载HTML文本文件,我们把它读到一个buf中,
  87. 第二步我们进行解析出GumboOutput数据结构
  88. 第三步在GumboOptout这个数据结构中找出title标签
  89. 最后我们输出内容,gumbo的步骤基本上就是这个样子的了,使用gcc编译的时候需要加上
  90. -lgumbo
  91. 下面再说一个例子,该例子中的HTML文件内容是各国DNSIP地址以及物理地址,大概的格式是
  92.  
  93. <dt><dd class="ipstart">开始ip地址</dd><dd class="ipend">结束ip地址</dd><dd class="address">物理地址</dd></dt>
  94. 我们的解析步骤是获取所有dt标签再获取所有dd标签,然后分别输出dd标签中class属性为ipstartipendaddress的内 容,下面放代码,由于原HTML文本文件内容放多,我不便放上来,这里就使用在线抓取的方式获取HTML文本,所以这里给出的是HTML文本的url 址,至目前写代码这一刻该程序还是完全能够正常工作的,日后会该网页是否会因该网页做调整等原因解析出错就不得而知了。
  95.  
  96. #include <stdio.h>
  97. #include <string.h>
  98. #include <stdlib.h>
  99. #include <oauth.h>
  100. /* 包含头文件 */
  101. #include <gumbo.h>
  102.  
  103. #define URL "http://ip.yqie.com/dns_usa.htm"
  104.  
  105. void print_dns(GumboNode *node,GumboAttribute *attr)
  106. {
  107. /* 获取子节点 */
  108. GumboNode *ip=(GumboNode *)(&node->v.element.children)->data[];
  109.  
  110. /* 根据class属性的值打印结果 */
  111. if(strcmp(attr->value,"ipstart") == )
  112. {
  113. if(ip->type == GUMBO_NODE_TEXT)
  114. printf("开始IP:%s ",ip->v.text.text);
  115. }
  116. else if(strcmp(attr->value,"ipend") == )
  117. {
  118. if(ip->type == GUMBO_NODE_TEXT)
  119. printf("结束IP:%s ",ip->v.text.text);
  120. }
  121. else if(strcmp(attr->value,"address") == )
  122. {
  123. if(ip->type == GUMBO_NODE_TEXT)
  124. printf("物理地址:%s\n",ip->v.text.text);
  125. }
  126. }
  127.  
  128. void get_dns(GumboNode *node,GumboTag tag)
  129. {
  130. GumboVector *children;
  131. GumboAttribute *attr;
  132. int i;
  133.  
  134. if(node->type != GUMBO_NODE_ELEMENT) return;
  135. /* 获取当前节点class属性 */
  136. if(attr=gumbo_get_attribute(&node->v.element.attributes,"class"))
  137. print_dns(node,attr);
  138.  
  139. /* 当前节点子节点 */
  140. children=&node->v.element.children;
  141. /* 如果当前节点标签为td我们就查找dd标签 */
  142. if(node->v.element.tag == GUMBO_TAG_DT)
  143. for(i=;i < children->length;++i)
  144. get_dns(children->data[i],GUMBO_TAG_DD);
  145.  
  146. /* 查找所有<dt>标签 */
  147. for(i=;i < children->length;++i)
  148. get_dns(children->data[i],GUMBO_TAG_DT);
  149. }
  150.  
  151. int main(void)
  152. {
  153. GumboOutput *output;
  154. char *buf;
  155.  
  156. /* 下载HTML文本文件 */
  157. buf=oauth_http_get(URL,NULL);
  158. if(!buf) return-;
  159. /* 解析 */
  160. output=gumbo_parse(buf);
  161. if(!output)
  162. {
  163. free(buf);
  164. return -;
  165. }
  166. /* 获取我们想要的内容 <dt>*/
  167. get_dns(output->root,GUMBO_TAG_DT);
  168.  
  169. /* 释放资源 */
  170. gumbo_destroy_output(&kGumboDefaultOptions,output);
  171. free(buf);
  172.  
  173. return ;
  174. }
  175. 由于使用了oauth所以使用gcc编译时需要加上-loauth参数

【c语言】使用gumbo解析HTML的更多相关文章

  1. C语言文件操作解析(五)之EOF解析(转载)

      C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符.但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特 ...

  2. 【转】C语言文件操作解析(三)

    原文网址:http://www.cnblogs.com/dolphin0520/archive/2011/10/07/2200454.html C语言文件操作解析(三) 在前面已经讨论了文件打开操作, ...

  3. C语言创建及解析Json的使用法则

    参考原文:http://blog.csdn.net/xukai871105/article/details/33013455 JSON(JavaScriptObject Notation)是一种轻量级 ...

  4. 在浏览器的背后(二) —— HTML语言的语法解析

    当你看到这篇文章意味着我辜负了@教主的殷切期望周末木有去约会,以及苏老师@我思故我在北京鼓楼的落井下石成功了…… 本文demo powered by 已经结婚的@老赵的不再维护的wind.js 物是人 ...

  5. 纯C语言INI文件解析

    原地址:http://blog.csdn.net/foruok/article/details/17715969 在一个跨平台( Android .Windows.Linux )项目中配置文件用 IN ...

  6. c语言复杂声明解析

    这是个好东西,接触c语言好几年了,第一次看到这东西,惊喜万分. 先提供个分析案例,以后看方便 vector <int> * (*seq_array[]) (int )={func1,fun ...

  7. C语言之歌词解析

    0x00 脚下的路 不知道为啥要写这个小标题,可能是年轻的心想体验一下苍老的感觉,抑或是少年的一阵迷茫.混沌的四年,终究还是入了这一行.从初时的不知,到现在的刚开始,中间的间隔竟是四年之久,想起了陈奕 ...

  8. Go语言 命令行解析(一)

    命令行启动服务的方式,在后端使用非常广泛,如果有写过C语言的同学相信不难理解这一点!在C语言中,我们可以根据argc和argv来获取和解析命令行的参数,从而通过不同的参数调取不同的方法,同时也可以用U ...

  9. [JZOJ3588]【中山市选2014】J语言(表达式解析+栈)

    Description J语言作为一门编程语言,诞生于20世纪90年代.............. 好学的小H今天又学到了一种新东西——J语言.显然,J语言的背景已经被小H忘得一干二净了,但是小H仍然 ...

随机推荐

  1. win7 fiddler报“Creation of the root certificate was not successful”的问题

    cd "C:\Program Files (x86)\Fiddler2" makecert.exe -r -ss my -n "CN=DO_NOT_TRUST_Fiddl ...

  2. 《Android源码设计模式》--装饰模式

    No1: Activity继承于ContextThemeWrapper,继承于ContextWrapper,继承于Context. No2: Context中方法的所有实现均由ContextImpl类 ...

  3. PIL 学习

    参考资料:Python图像处理库:pillow Image 类 Pillow 中最重要的类就是 Image,该类存在于同名的模块中.可以通过以下几种方式实例化:从文件中读取图片,处理其他图片得到,或者 ...

  4. 最详细的vue-cli安装教程 &^没有之一 ^& 大神亲测。。╮( ̄▽  ̄)╭

    这里介绍使用git安装,电脑自带命令行依然可以使用进行安装 第一步 node环境安装 1.1 如果本机没有安装node运行环境,请下载node 安装包进行安装 1.2 如果本机已经安装node的运行换 ...

  5. 美团 R 语言数据运营实战

    一.引言 近年来,随着分布式数据处理技术的不断革新,Hive.Spark.Kylin.Impala.Presto 等工具不断推陈出新,对大数据集合的计算和存储成为现实,数据仓库/商业分析部门日益成为各 ...

  6. JAVAEE——BOS物流项目02:学习计划、动态添加选项卡、ztree、项目底层代码构建

    1 学习计划 1.jQuery easyUI中动态添加选项卡 2.jquery ztree插件使用 n 下载ztree n 基于标准json数据构造ztree n 基于简单json数据构造ztree( ...

  7. Django MiddleWare初识

    一.Django 中间件介绍 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定 ...

  8. MySQL 语句分析

    公司使用的数据库是 MySQL 数据库,我对于 MySQL 的了解仅仅是上学的时候学过PHP略微了解. 我认为,作为一个后端程序员,除了在意功能能不能实现之外, 在实现功能之后,还要去想有没有更好的办 ...

  9. 【洛谷】2602: [ZJOI2010]数字计数【数位DP】

    P2602 [ZJOI2010]数字计数 题目描述 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 输入输出格式 输入格式: 输入文件中仅包含一行两个整数a ...

  10. HDU 5699 货物运输 二分

    货物运输 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5699 Description 公元2222年,l国发生了一场战争. 小Y负责领导工人运输物 ...