htmlcxx c ++抓取html

时间:2011-02-22 16:51:15

标签: c++

我已经从不同的人那里读到了许多关于库来抓取HTML的不同问题。我决定使用htmlcxx,因为它看起来很简单,它在Ubuntu存储库中。无论如何,在玩htmlcxx时,我试图实现一个简单的任务并在标题标签之间抓取文本。使用迭代器,it-> text()返回标记本身,它 - > textClosing()返回标记的结束。我的问题是,我如何获得标签之间的数据?我的意思是,必须有一种方法,为什么要使一个库来抓取HTML而没有这个功能?如果有人能指出我正确的方向,我会很感激。

你可以看看我到目前为止用svn做了什么: svn co svn://yunices.dyndns.org/repository/nich/trunk。

或通过websvn查看: https://yunices.dyndns.org/

以下是相关的特定代码段:

void node::get_headings() {
    tree<htmlcxx::HTML::Node>::iterator it = dom.begin();
    tree<htmlcxx::HTML::Node>::iterator end = dom.end();
    for (; it != end; ++it) {
        static const boost::regex expression("[h|H][1-6]");
        if(boost::regex_search(it->tagName(), expression)) {
            it->parseAttributes();
            std::cout << it->text() << "<=>" << it->closingText() << std::endl;
            std::map<std::string, std::string> pairs = it->attributes();
            for ( std::map<std::string, std::string>::const_iterator iter = pairs.begin();
                    iter != pairs.end(); ++iter ) {
                std::cout << iter->first << ":" << iter->second << "\n";
            }
        }
    }
}

3 个答案:

答案 0 :(得分:4)

在大多数DOM库中(如果我正确读取代码,在htmlcxx中),标签的文本实际上是一个节点(或者在类似

的情况下)
  

<p> bla <p>blubb</p> blah </p>

多个节点。)

您只需迭代标记的所有子项,并检查它既不是注释也不是标记。

答案 1 :(得分:2)

您可以将此方法添加到Node.h以获取标记之间包含的内容(将原始html字符串作为参数传递):

inline unsigned int contentLength() const { this->mLength - this->mText.length() - this->mClosingText.length(); }
inline std::string content(const std::string& html) const { return html.substr(this->mOffset + this->mText.length(), this->contentLength()); }

这很好用戴夫,谢谢,实际上有一个支架丢失,我只是把它扔进一行。

inline std::string content(const std::string& html) const { return html.substr(this->mOffset + this->mText.length(), this->mLength - (this->mText.length() + this->mClosingText.length())); }

答案 2 :(得分:2)

以下函数演示了访问子内容的方法。

std::string get_child_content( tree<HTML::Node> const & dom, tree<HTML::Node>::iterator const & parent )
   {
   std::string result;
   for ( unsigned i=0; i<dom.number_of_children(parent); i++ )
      {
      tree<HTML::Node>::iterator it = dom.child(parent,i);
      if ( !it->isTag() && !it->isComment() ) result += it->text();
      }
   return result;
   }

请记住,正如@filmor所指出的,HTML可能代表任何标记的多个级别的后代。我提供的功能只捕获直接的孩子。

以下是一个如何使用此示例以及对某些示例HTML的影响的示例...

cout << it->text(); // display the opening tag
cout << get_child_content(dom,it); // display the contents
cout << it->closingText(); // display the closing tag

原始HTML ...

<h2>hello <span>w</span>orld</h2>

产生的结果(注意到跨度及其内容缺失)......

<h2>hello orld</h2>