【问题标题】:How do I extract the "href" attributes from a HTML document with select.rs?如何使用 select.rs 从 HTML 文档中提取“href”属性?
【发布时间】:2018-02-28 01:54:24
【问题描述】:

我正在尝试编写一个非常基本的爬虫。收到 HTTP 响应后,我使用 select.rs crate 从正文中提取 URL 以进行进一步爬取。

如何使用“for-iteration”从作为 HTTP 响应的“正文”部分的“文档”中提取这些 URL?

extern crate hyper;
extern crate select;
extern crate xhtmlchardet;
extern crate robotparser;
extern crate url;

use std::io::Read;
use Crawler::hyper::client::Client;
use Crawler::hyper::header::Connection;
use Crawler::select::document::Document;
use Crawler::select::predicate::*;

pub fn crawl(url: &str) {

    //Opens up a new HTTP client
    let client = Client::new();

    //Creates outgoing request
    let mut res = client.get(&*url)
        .header(Connection::close())
        .send().unwrap();

    //Reads the response
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    println!("Response: {}", res.status);
    println!("Headers:\n{}", res.headers);
    println!("Body:\n{}", body);


    let document = Document::from_str(&*body);

    for node in document.find(Attr("id", "hmenus")).find(Name("a")).iter() {
        println!("{} ({:?})", node.text(), node.attr("href").unwrap());
    }
}

对诸如“um.ac.ir”之类的 URL 执行抓取的结果是带有正文的完整 HTTP 响应。我正在尝试从此输出中提取hrefs。

Response: 200 OK
Headers:
X-Content-Type-Options: nosniff
X-Frame-Options: sameorigin
Cache-Control: cache
Date: Tue, 27 Feb 2018 13:16:27 GMT
Vary: Accept-Encoding
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Transfer-Encoding: chunked
Pragma: no-cache
Server: GFW/2.0
Connection: close
Content-Type: text/html; charset=utf-8
Strict-Transport-Security: max-age=63072000; preload
Set-Cookie: POSTNUKESID=pnd2nuadgastqak5h6nop87c63; path=/

...

<div class="col-md-4">
    <h3>سایر</h3>
    <ul> 
        <li><a target="_blank" href="http://ftpnews.um.ac.ir/">سایت خبری ftp دانشگاه</a></li>
        <li><a target="_blank" href="http://news.um.ac.ir/Topic96.html">گزینش دانشگاه </a></li>
        <li><a target="_blank" href="http://herasat.um.ac.ir/index.php?lang=fa">مدیریت حراست دانشگاه </a></li>
        <li><a target="_blank" href="http://mafakher.um.ac.ir/">مركز آثارمفاخر و اسناد دانشگاه</a></li>
        <li><a target="_blank" href="http://intr.um.ac.ir/">مدیریت همكاری های علمی و بین المللی</a></li>
        <li><a target="_blank" href="http://eva.um.ac.ir/"> مدیریت نظارت و ارزیابی دانشگاه</a></li>
        <li><a target="_blank" href="http://saybanemehr.um.ac.ir/">سایت سایبان مهر</a></li>
        <li><a target="_blank" href="http://faf.um.ac.ir/">بنیاد دانشگاهی فردوسی</a></li>
        <li><a target="_blank" href="http://ads.um.ac.ir/">آگهي ها و تبليغات دانشگاه</a></li>
        <li><a target="_blank" href="http://fumblog.um.ac.ir/">سامانه مدیریت وبلاگ</a></li>
        <li><a target="_blank" href="http://basijasatid.um.ac.ir/">بسیج اساتید</a></li>
        <li><a target="_blank" href="http://basij.um.ac.ir/">بسیج كاركنان</a></li>
        <li><a target="_blank" href="http://nahad.um.ac.ir/">نهاد نمایندگی رهبری در دانشگاه</a></li>
    </ul> 
</div>

...   

问题是println!("{} ({:?})", node.text(), node.attr("href").unwrap()) 没有输出任何东西,因为[...].iter() 工作不正常:

for node in document.find(Attr("id", "hmenus")).find(Name("a")).iter() {
        println!("{} ({:?})", node.text(), node.attr("href").unwrap());
    }

find(Attr("id", "hmenus")).find(Name("a")) 似乎不是从 HTTP 响应正文中查找“href”标签的正确方法。

我相信重写这部分应该可以解决我的代码中的问题,尽管它需要全面了解 select::document 的工作原理。

【问题讨论】:

  • 您忘记说明您的代码的问题是什么。从表面上看,它似乎可行。
  • 问题出在最后一部分,正如我提到的,我需要帮助编写代码的“for-iteration”部分。
  • 你已经已经写过那部分了。来自您的代码:for node in document.find(Attr("id", "hmenus")).find(Name("a")).iter()。那是一个for循环。它迭代。目前还不清楚到底是什么问题。
  • 好吧,我相应地编辑了问题并在代码的“for-iteration”部分指定了问题,抱歉造成误解,希望对您有所帮助。
  • 似乎 [...] 不是正确的方式 — 但是为什么它“看起来”不是正确的方式?您是否收到编译错误、运行时错误、不正确/格式错误的数据等? 我相信重写这部分应该可以解决问题——你还没有说你遇到的问题是什么

标签: http rust


【解决方案1】:

我假设您从一些示例代码中复制了 Attr("id", "hmenus")。这是一个过滤谓词,匹配包含属性id="hmenus" 的HTML 节点。您的示例页面 um.ac.ir 不包含任何具有属性 id="hmenus" 的节点。如果您希望爬虫找到页面上的所有 节点,过滤谓词将是Name("a")

for node in document.find(Name("a")).iter() {
    if let Some(href) = node.attr("href") {
        println!("{} ({:?})", node.text().trim(), href);
    }
}

【讨论】:

  • 谢谢你的回答,这段代码解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 2020-03-03
  • 2018-12-08
  • 1970-01-01
相关资源
最近更新 更多