一个C++写的html解析库的简介

学习Qt也有段时间了,前一阵子想着写一个Qt版的博客园桌面端。现阶段主要想实现:

(1)显示博客园主页的推荐的那个些文章的条目(包括作者的图像、该博客的浏览次数、发布时间等)。

(2)可以登陆自己的博客园账号,并显示自己的博客文章。

(3)点击显示的博客文章条目时可以弹出窗口显示该片博客的内容。

同时还要实现自动刷新功能。

但是在编写的过程中,需要跟reply回来的html文档打交道,需要一个可以解析html文档的库。我在网上搜索了找到了C++编写的html解析库有htmlcxx、和google的gumbo-parser,还有几个其他的库,使用较多的是htmlcxx和gumbo-parser。但是在实际的使用中,我发现htmlcxx虽然解析的很好但是使用起来很不方便,不能够自己定制类似于JS的document.getElementById()以及document.getElementByName()这样的函数,同时查找html标签也很困难(可能是我没有深入的研究,个人感觉),而gumbo-parser是linux和unix下的,因为里面用到了几个函数在windows上没有提供位于string.h头文件,所以基于这个情况,我便自己编写了一个html文档解析库。经过了很多页面的测试,解析的比较准确,至少我使用博客园首页的html源码解析时通过自己的get_element_by_id函数能正确的获取到各个标签节点。

在完成该桌面端之后,我会把源代码贡献出来,同时也会给出一些使用的案例。希望对大家有帮助,该库会在以后不断的扩展,实现CSS选择器选取标签元素的功能,使我们可以更方便的使用。

现在不废话了,直接上一个小案例。

首先,我们需要准备博客园首页的html文档(在浏览器页面中邮件选择源码既可以获得,然后赋值粘贴保存到一个txt文件中)。

然后,分析一下博客园中间部分推荐的博客文章的条目,在该html中的结构。可以看到这20个条目全部包含在一个id=‘post_list‘的div中,而每一个条目又是包含在class=‘post_item‘的div中。

<div id="post_list">
    <div class="post_item">
        <div class="digg">
            <div class="diggit" onclick="DiggPost(‘wenjianmuran‘,5049966,256767,1)">
            <span class="diggnum" id="digg_count_5049966">0</span>
        </div>
        <div class="clear"></div>
        <div id="digg_tip_5049966" class="digg_tip"></div>
        </div>
        <div class="post_item_body">
        <h3>
                <a class="titlelnk" href="http://www.cnblogs.com/wenjianmuran/p/5049966.html" target="_blank">Python爬虫入门案例:获取百词斩已学单词列表</a>
            </h3>
            <p class="post_item_summary">
                <a href="http://www.cnblogs.com/wenjianmuran/" target="_blank"><img width="48" height="48" class="pfs" src="http://pic.cnblogs.com/face/728333/20151201230814.png" alt=""/></a>    百词斩是一款很不错的单词记忆APP,在学习过程中,它会记录你所学的每个单词及你答错的次数,通过此列表可以很方便地找到自己在记忆哪些单词时总是反复出错记不住。我们来用Python来爬取这些信息,同时学习Python爬虫基础。首先来到百词斩网站:http://www.baicizhan.com/logi...
        </p>
        <div class="post_item_foot">
        <a href="http://www.cnblogs.com/wenjianmuran/" class="lightblue">文剑木然</a>
        发布于 2015-12-16 00:37
        <span class="article_comment">
            <a href="http://www.cnblogs.com/wenjianmuran/p/5049966.html#commentform" title="" class="gray">评论(0)</a>
        </span>
        <span class="article_view">
            <a href="http://www.cnblogs.com/wenjianmuran/p/5049966.html" class="gray">阅读(20)</a>
        </span>
        </div>
    </div>
    <div class="clear"></div>
    </div>
</div> 

接下来,就是需要解析并获取这些条目的标题并输出。

#ifndef HTML_
#define HTML_

#include <Windows.h>
#include <string>
#include <iostream>

std::string html;

void init_html(){
    HANDLE hFile = CreateFile(TEXT("./cnblog.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE){
        int size = GetFileSize(hFile, NULL);
        std::cout << "file size : " << size << std::endl;
        char * p = new char[size + 1];
        DWORD dwReads;
        ReadFile(hFile, p, size, &dwReads,NULL);
        p[dwReads] = 0;
        CloseHandle(hFile);
        AllocConsole();
        html.assign(p);
        delete [] p;
    }else{
        std::cout << "can not open file" << std::endl;
    }

}
#endif

上面是读取html文档内容的函数。(需要注意的是:使用该方式读取的时需要将文件保存为ANSI格式的,否则会出现中文乱码)

#include "htmlparser.h"
#include "parentnode.h"
#include "html.h"

using namespace std;

int main(){
    init_html();
    hunter::HtmlParser parser;
    parser.parser_html(html.c_str());
    std::cout << "finished parser..." << std::endl;

    Node * node = parser.get_element_by_id(std::string("post_list"));
    if (parser.error().empty()){
        if (node == 0){
            std::cout << "Can‘t find this node..." << std::endl;
        }
        else{
            std::vector<Node *> childs = parser.get_childs_by_class(node, "div", "class", "post_item");
            for (int i = 0; i<childs.size(); i++){
                Node * divnode = childs.at(i);
                std::vector<Node *> divchilds = parser.get_childs_by_class(divnode, "div", "class", "post_item_body");
                if (divchilds.size()>0){
                    Node * divchild = divchilds.at(0);
                    Node * h3 = parser.get_child_tag(divchild, "h3");
                    if (h3 != 0){
                        Node * a = parser.get_child_tag(h3, "a");
                        std::cout << parser.get_tag_text(a) << std::endl;
                    }
                }
            }
        }
    }
    else{
        std::cout << parser.error() << std::endl;
    }

    std::cin.get();

    return 0;
}

解析html,同时使用了几个函数parser.get_element_by_id(std::string("post_list"))、parser.get_childs_by_class(node, "div", "class", "post_item")、parser.get_child_tag(divchild, "h3")和parser.get_tag_text(a)。这些函数是用来获取相应标签节点的,好了下面看下输出的结果:

看看,是不是解析并成功获取到了首页20个条目的信息。

时间: 2024-12-13 17:57:47

一个C++写的html解析库的简介的相关文章

inifile 一个轻量级的INI文件解析库

ini文件是一种常见的配置文件.它以简单的文字与简单的结构组成.INI文件会以不同的扩展名,如".ini.",".cfg",".conf"等. INI文件的格式 INI文件由3个重要的部分组成:参数(parameters),段(sections)和注释(comments).其格式如下: 段(sections) [section] 参数(parameters) name=value 注释(comments) ;comments 每个段包括段名,注释

第四部分 解析库的使用(XPath、Beautiful Soup、PyQuery)

在网页节点中,可以定义id.class或其他属性.节点间有层次关系,网页中要通过XPath或CSS选择器定位一个或多个节点.在页面解析时,可利用XPath或CSS选择器提取某个节点,再调用相应方法获取它的正文内容或者属性,就可提取到想要的信息.在python中常用的解析库有lxml.Beautiful Soup.pyquery等.使用这些库可以很大程度上提高效率. 一 使用XPath解析库 XPath,全称XML Path Language,即XML路径语言,是一门在XML文档中查找信息的语言.

Python 爬虫 解析库的使用 --- Beautiful Soup

知道了正则表达式的相关用法,但是一旦正则表达式写的有问题,得到的可能就不是我们想要的结果了.而且对于一个网页来说,都有一定的特殊结构和层级关系,而且有很多节点都有id或class来做区分,所以借助它们的结构和属性来提取也可以. 本随笔内容就来介绍一个强大的解析工作Beautiful Soup,它借助网页的结构和属性等特性来解析网页.有了它,我们不用再去写一些复杂的正则表达式,只需要简单的几条语句,就可以完成网页中某个元素的提取. 1.简介 简单来说,Beautiful Soup 就是Pyhon

TinyWS —— 一个C++写的简易WEB服务器(三)

写在前面 代码已经托管在 https://git.oschina.net/augustus/TinyWS.git 可以用git clone下来.由于我可能会偶尔做一些修改,不能保证git 库上的代码与blog里的完全一致(实际上也不可能把所有的代码都贴在这里).另外,TinyWS是基于linux写的(ubuntu 14.10 + eclipse luna,eclipse工程我也push到了git库),故在Windows上可能无法正常编译(主要是系统调用 部分可能会不同). 前面的内容可参考上一篇

cmdline —— 轻量级的C++命令行解析库

平时用C++写一些命令行工具,需要解析命令行的输入参数,这是一项繁琐并且容易出错的工作,我们不应该将主要精力放在这上面,可以考虑使用开源的库,下面的cmdline就是其中非常好用的一款. cmdline介绍 cmdline 是一个非常简单好用的C++命令行解析库,其基于模板,所以使用很简单,写出的代码也很优雅.由于其只包含一个头文件,所以很容易集成到自己的项目中. cmdline项目托管地址Github:https://github.com/tanakh/cmdline cmdline使用 下面

从DNS基础到在CentOS6.5上&ldquo;玩着&rdquo;搭建一个支持正向、反向解析的&ldquo;

1.什么是DNS? (Domain Name System)域名系统. DNS其实实现的功能很简单也很有效,它能够让用户可以不用记得那些经常要访问服务器的ip地址,直接要你输入类似拼音格式的就可以访问到那些数字串的ip地址.假设以61.120.155.14(举个例子),我们总是用这些数字进行网页服务器的访问岂不是很蛋疼,毕竟很多人还是对文字甚至拼音字母更容易让正常人记忆.这就是DNS的功能. 当然,它不仅能把那些你输入的拼音字母转换成ip地址的数字串,它还支持把那些数字串转换成你想访问的实际的网

OpenStack配置解析库——oslo.config

OpenStack的oslo项目旨在独立出系统中可重用的基础功能,oslo.config就是其中一个被广泛使用的库,该项工作的主要目的就是解析OpenStack中命令行(CLI)或配置文件(.conf)中的配置信息.下面先给一个high-level的过程说明一下如何使用这个库. OpenStack中配置文件的使用主要有以下几个步骤, step1. 正确配置各个服务主配置文件(.conf文件),在各个服务中完成. step2. 在要使用到配置文件的模块中声明这个模块将会用到的那些配置项(比如'au

Android JSON解析库Gson和Fast-json的使用对比和图书列表小案例

Android JSON解析库Gson和Fast-json的使用对比和图书列表小案例 继上篇json解析,我用了原生的json解析,但是在有些情况下我们不得不承认,一些优秀的json解析框架确实十分的好用,今天我们为了博客的保质保量,也就不分开写,我们直接拿比较火的Gson和Fast-json来使用,末尾在进行一些分析 Android JSON原生解析的几种思路,以号码归属地,笑话大全,天气预报为例演示 一.各有千秋 两大解析库的东家都是巨头,一个来自于Google官方,一个来自阿里巴巴,我们这

【C++】cmdline —— 轻量级的C++命令行解析库

平时用C++写一些命令行工具,须要解析命令行的输入參数,这是一项繁琐而且easy出错的工作,我们不应该将主要精力放在这上面.能够考虑使用开源的库.以下的cmdline就是当中很好用的一款. cmdline介绍 cmdline 是一个非常easy好用的C++命令行解析库,其基于模板.所以使用非常easy,写出的代码也非常优雅. 因为其仅仅包括一个头文件.所以非常easy集成到自己的项目中. cmdline项目托管地址Github:https://github.com/tanakh/cmdline