我已经从不同的人那里读到了许多关于库来抓取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";
}
}
}
}
答案 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>