webcrawler链接提取问题

时间:2011-05-16 05:31:53

标签: c++

我正在写一个简单的webcrawler。问题是,链接提取。

我使用cpp-netlib和boost。这里有几行我的CLink Class。

    CLink::CLink(const CLink& father, const std::string& relUrl )
    {
     uri = relUrl;
     boost::network::uri::uri instance(relUrl);
     boost::network::uri::uri instanceFather(father.uri);

     if ( (valid = boost::network::uri::is_valid(instance)) == 1)
      {
       scheme    = boost::network::uri::scheme(instance);
       user_info = boost::network::uri::user_info(instance);
       host      = boost::network::uri::host(instance);
       port      = boost::network::uri::port(instance);
       path      = boost::network::uri::path(instance);
       query     = boost::network::uri::query(instance);
       fragment  = boost::network::uri::fragment(instance);

       uri  = scheme;
       uri += "://";
       uri += host;
       uri += path;

      }
     else
      {
       if ( (valid = boost::network::uri::is_valid(instanceFather)) == 1)
        {

         scheme    = boost::network::uri::scheme(instanceFather);
         user_info = boost::network::uri::user_info(instanceFather);
         host      = boost::network::uri::host(instanceFather);
         port      = boost::network::uri::port(instanceFather);
         path      = boost::network::uri::path(instance);
         query     = boost::network::uri::query(instance);
         fragment  = boost::network::uri::fragment(instance);

         uri  = scheme;
         uri += "://";
         uri += host;
         uri += path;

        }
      }
    };

    CLink::CLink( const std::string& _url )
    {

     uri = _url; 
     boost::network::uri::uri instance(_url);
      if ( (valid = boost::network::uri::is_valid(instance) ) == 1)
       {
       scheme    = boost::network::uri::scheme(instance);
       user_info = boost::network::uri::user_info(instance);
       host      = boost::network::uri::host(instance);
       port      = boost::network::uri::port(instance);
       path      = boost::network::uri::path(instance);
       query     = boost::network::uri::query(instance);
       fragment  = boost::network::uri::fragment(instance);


       uri  = scheme;
       uri += "://";
       uri += host;
       uri += path;

         }
        else
      std::cout << "err " << std::endl;
    };

我使用htmlcxx lib获取的网页链接。我使用HTML :: Node并使用boost文件系统对它们进行规范化。

 if ( url.find("http://") == std::string::npos)
  {
   std::string path = link.get_path() + url;   
   url =  link.get_host() + path;

   boost::filesystem::path result;
   boost::filesystem::path p(url);
   for(boost::filesystem::path::iterator it=p.begin(); it!=p.end(); ++it)
    {
     if(*it == "..")
      {
       if(boost::filesystem::is_symlink(result) )
    result /= *it;
       else if(result.filename() == "..")
    result /= *it;
       else
    result = result.parent_path();
      }
     else if(*it == ".")
      {
       // Ignore
      }
     else
      {
       // Just cat other path entries
       result /= *it;
      }
    }

   url = "http://" + result.string();
  }

 return ret;

现在的问题是。

我尝试获取http://www.wikipedia.de/,我得到了像

这样的网址

属性 http://wikimedia.de/wiki/Vereinszeitung   ......

并在网站http://wikimedia.de/wiki/Vereinszeitung上有一个类似/wiki/vereinsatzung

的链接

经常我得到像

这样的链接
http://wikimedia.de/wiki/Vereinszeitung/wiki/Freies_Wissen

有人有想法吗?

1 个答案:

答案 0 :(得分:1)

您需要有绝对链接的特殊情况(以/开头的那些)。

如果href/开头,那么结果链接应该是(使用来自RFC的来自The URI template的条款):

[scheme]://[authority][what you got in href]

您目前正在构建的是:

[scheme]://[authority][path][what you got in href]

所以你要复制路径信息。

因此,如果link.get_path()/开头,则只需更改:

std::string path = link.get_path() + url;   
url =  link.get_host() + path; // this is incorrect btw, missing the [port]

url =  link.get_host() + ":" + link.get_port() + url;

在路径上进行路径规范化可能更简洁,而不是在URL上(即在规范化路径后添加host:port)。

[我认为如果遇到https链接,您的代码就会失败。]