【问题标题】:Identify a weblink in bold in R在 R 中识别粗体的网络链接
【发布时间】:2016-08-31 21:46:00
【问题描述】:

以下脚本允许我访问一个包含多个名称相似的链接的网站。我只想得到其中一个,因为它在网站上以 bold 打印,因此可以与其他区别开来。但是,我找不到在列表中选择粗体链接的方法。

有人对此有意见吗? 提前致谢!

library(httr)
library(rvest)
sp="Alnus japonica"

res <- httr::POST(url ="http://apps.kew.org/wcsp/advsearch.do", 
              body = list(page ="advancedSearch", 
                          AttachmentExist ="", 
                          family ="", 
                          placeOfPub ="", 
                          genus = unlist(strsplit(as.character(sp), split="         "))[1], 
                          yearPublished ="", 
                          species = unlist(strsplit(as.character(sp), split="    "))[2], 
                          author ="", 
                          infraRank ="", 
                          infraEpithet ="", 
                          selectedLevel ="cont"), 
              encode ="form") 
pg <- content(res, as="parsed") 
lnks <- html_attr(html_nodes(pg,"a"),"href")
#how get the url of the link wth accepted name (in bold)?
res2 <- try(GET(sprintf("http://apps.kew.org%s", lnks[grep("id=",lnks)]      [1])),silent=T)
#this gets a link but often fails to get the bold one

【问题讨论】:

  • 这在很大程度上取决于它是如何加粗的。如果是内联样式,那很容易,但它可能是将 CSS 应用于特定的 id 或类,这意味着要深入研究代码。
  • 如果你手动搜索,你确实会得到一个&lt;b&gt;标签,但它似乎没有出现在httr结果中,所以它必须在事后以某种方式插入。
  • 链接被&lt;b&gt; 标签包围,所以你应该能够以这种方式获得它们。就像 alistaire 说的,不知道为什么 httr 会删除它们(我对 httr 没有经验,可能有一个选项......)
  • libxml2(支持rvestXML)不如浏览器灵活。在&lt;p&gt; 之外的&lt;b&gt; 在技术上是无效的HTML/XML,libxml2 以这种方式解析它。

标签: html r rvest httr


【解决方案1】:

在我看来,rvest/httr 可能存在错误,因为&lt;b&gt; 在相关链接上似乎围绕着&lt;a href...&gt;,但在解析后的版本中却没有。

我用过:

library(rvest)
sp=strsplit("Alnus japonica", " ")[[1]]

session <- html_session("http://apps.kew.org/wcsp/advsearch.do")
form <- html_form(session)[[1]]

filled_form <- set_values(form, genus = sp[1], species = sp[2])

out <- submit_form(session, filled_form)

看下面:

out %>% html_nodes(xpath = "descendant-or-self::*") %>% `[`(81:90)
# {xml_nodeset (10)}
#  [1] <p><a href="/wcsp/namedetail.do;jsessionid=F6180417706056852E58C1E290B5087A? ...
#  [2] <a href="/wcsp/namedetail.do;jsessionid=F6180417706056852E58C1E290B5087A?nam ...
#  [3] <i>Alnus</i>
#  [4] <i> japonica</i>
#  [5] <b>\n        </b>
#  [6] <p><a href="/wcsp/namedetail.do;jsessionid=F6180417706056852E58C1E290B5087A? ...
#  [7] <a href="/wcsp/namedetail.do;jsessionid=F6180417706056852E58C1E290B5087A?nam ...
#  [8] <i>Alnus</i>
#  [9] <i> japonica</i>
# [10] <p><a # href="/wcsp/namedetail.do;jsessionid=F6180417706056852E58C1E290B5087A? ...

如您所见,&lt;b&gt; 节点显示为空。但是,当我在 Chrome 上手动输入搜索并 View Source 时,我看到:

<b>
    <p><a href="/wcsp/namedetail.do?name_id=6471" class="onwardnav"><i>Alnus</i><i> japonica</i> (Thunb.) Steud., Nomencl. Bot., ed. 2, 1: 55 (1840).</a>
    </p>
</b>

相关的&lt;a&gt; 介于&lt;b&gt;&lt;/b&gt; 之间,告诉我它应该是&lt;b&gt; 的子对象,但这是空白:

out %>% html_nodes(xpath = "//b/child::*")

诚然,我不是 xpath 专家,所以我可能在这里搞砸了。希望这对您有所帮助。

【讨论】:

    【解决方案2】:

    首先,获取tidy-html5(它适用于几乎所有东西)并安装它并确保它在您的PATH 中。

    正如我的评论所说,浏览器在&lt;p&gt; 之外处理&lt;b&gt;,因为它们需要防弹。 libxml2 没有。所以,我们需要先清理一下(我现在需要制作一个新的tidyhtml 包),然后处理整理后的版本:

    library(xml2)
    library(httr)
    library(rvest)
    
    res <- httr::POST(url ="http://apps.kew.org/wcsp/advsearch.do", 
                  body = list(page ="advancedSearch", 
                              AttachmentExist ="", 
                              family ="", 
                              placeOfPub ="", 
                              genus = "Alnus", 
                              yearPublished ="", 
                              species = "japonica", 
                              author ="", 
                              infraRank ="", 
                              infraEpithet ="", 
                              selectedLevel ="cont"), 
                  encode ="form") 
    
    tf <- tempfile(fileext=".html")
    cat(content(res, as="text"), file=tf)
    
    tidy <- system2("tidy", c("-q", tf), TRUE)
    
    pg <- read_html(paste0(tidy, sep="", collapse=""))
    
    html_nodes(pg, xpath=".//p/b/a[contains(@href, 'name_id')]")
    
    ## {xml_nodeset (1)}
    ## [1] <a href="/wcsp/namedetail.do?name_id=6471" class="onwa ...
    

    如果 XPath 需要 CSS 选择器:

    html_nodes(pg, "p > b > a[href*='name_id']")
    

    更新

    我为libtidy 启动了一个基本的 pkg 包装器。如果你在 OS X 上使用 Homebrew,你可以这样做:brew install tidy-html5(安装上面的二进制文件和libtidy 库)和devtools::install_github("hrbrmstr/tidyhtml") 安装 pkg。那么,就是:

    library(xml2)
    library(httr)
    library(rvest)
    library(htmltidy)
    
    res <- httr::POST(url ="http://apps.kew.org/wcsp/advsearch.do", 
                  body = list(page ="advancedSearch", 
                              AttachmentExist ="", 
                              family ="", 
                              placeOfPub ="", 
                              genus = "Alnus", 
                              yearPublished ="", 
                              species = "japonica", 
                              author ="", 
                              infraRank ="", 
                              infraEpithet ="", 
                              selectedLevel ="cont"), 
                  encode ="form") 
    
    tidy_html <- tidy(content(res, as="text"))
    
    pg <- read_html(tidy_html)
    
    html_nodes(pg, "p > b > a[href*='name_id']")
    

    我应该能够让它在 Windows 和 linux 上工作,并使其成为一个真正的包(它现在是一个没有错误检查的瘦包装器),但这将在 TODO 上搁置一段时间。

    【讨论】:

    • 哇,太棒了!我要花一个星期才能弄清楚。
    • 非常感谢!我正在尝试使用 cmake 从 github 在 windows 64 中安装 tidy,但并不那么容易......任何好的教程都值得赞赏。
    • 他们有binaries for Windows。
    • 谢谢,现在这适用于示例,但不适用于其他物种,如 Abies amabilis。尽管是一个有效的名称,但我得到了这个错误: lnks
    • 你在最后一个)之前忘记了, "href"
    猜你喜欢
    • 2023-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    相关资源
    最近更新 更多