【问题标题】:readLines() webscraping cannot open connection in rreadLines() webscraping 无法在 r 中打开连接
【发布时间】:2023-04-03 05:25:01
【问题描述】:

我正在使用带有 R3.3.1 的 Windows 7。我有一个名为idsFinal_Attack 的数据框,它有两列。

Attack Type   
1                                                    40674 
2 Netcore.Netis.Devices.Hardcoded.Password.Security.Bypass 
3                                  DNS.Invalid.Size.Attack  
4                       Acunetix.Web.Vulnerability.Scanner  
5                                   SIPVicious.SIP.Scanner  
6                                                    17799   
New
1                                   SIPVicious.SIP.Scanner
2 Netcore.Netis.Devices.Hardcoded.Password.Security.Bypass
3                                  DNS.Invalid.Size.Attack
4                       Acunetix.Web.Vulnerability.Scanner
5                                   SIPVicious.SIP.Scanner
6                               MS.SMBv2.Infinite.Loop.DoS  

第一个是“攻击类型”,由字符 ID 和数字 ID 组成。第二列是我希望用下面的代码填写的内容。

URL = 'http://www.fortinet.com/ids/VID'
idsFinal_Attack$New = character(length = nrow(idsFinal_Attack))

for (i in 1:nrow(idsFinal_Attack)) {
    if (is.na(as.numeric(idsFinal_Attack$`Attack Type`[i]))) {
            idsFinal_Attack$New[i] = idsFinal_Attack$`Attack Type`[i]
    } else {
            fortinetPage = readLines(paste0(URL, idsFinal_Attack$`Attack Type`[i]))
            fortinetPage = grep("id=\"ency_title\">Vulnerability:", fortinetPage, 
                                value = TRUE)
            idsFinal_Attack$New[i] = 
                    gsub("<h1 id=\"ency_title\">Vulnerability: |</h1>", "", fortinetPage)
    }
}

对于“攻击类型”中包含字符串的行,我希望将该字符串复制并粘贴到“新建”列的相邻单元格中。对于“攻击类型”中包含数字条目的行,如第 1 行,我希望将该数值粘贴到变量“URL”的末尾,然后使用readLines() 函数提取网页的一部分,增强“ URL”变量将我带到,即http://www.fortinet.com/ids/VID40674。我只需要标题为“漏洞”的网页的一小部分以及后续文本。 readLines() 返回网页中的所有文本,然后我可以使用 grep 和 gsub 来获取所需的部分。数据框idsFinal_Attack 有 145 行,其中 67 行是数字,需要 readLines() 命令。下面的代码适用于其中大约一半,然后抛出如下所示的错误。

Error in readLines(url(paste0(URL, idsFinal_Attack$`Attack Type`[i]), 
:  cannot open the connection

这是我的第一次尝试,我意识到代码可以更简洁。我只是想获得一个工作版本。我曾简单地试验过 XML 和 rvest 包,但没有任何运气。有人有什么建议吗?

【问题讨论】:

  • 不要使用正则表达式解析 HTML。使用像 rvestXML 这样的 HTML 解析器。

标签: r web-scraping


【解决方案1】:

我认为readLines 可能无法正确处理重定向。由于 Fortinet 重定向,您可能会遇到麻烦。

我相信使用rvest 比使用readLines 更透明。

例如,一个可重现的例子是:

library(readr)
library(rvest)

sample.data <- "Attack Type New
40674   SIPVicious.SIP.Scanner
Netcore.Netis.Devices.Hardcoded.Password.Security.Bypass    Netcore.Netis.Devices.Hardcoded.Password.Security.Bypass
DNS.Invalid.Size.Attack DNS.Invalid.Size.Attack
Acunetix.Web.Vulnerability.Scanner  Acunetix.Web.Vulnerability.Scanner
SIPVicious.SIP.Scanner  SIPVicious.SIP.Scanner
17799   MS.SMBv2.Infinite.Loop.DoS
127 MS.SMBv2.Infinite.Loop.DoS"

idsFinal_Attack <- read_tsv(sample.data)

URL = 'http://www.fortinet.com/ids/VID'
idsFinal_Attack$New = character(length = nrow(idsFinal_Attack))

for (i in 1:nrow(idsFinal_Attack)) {
  attack.type <- idsFinal_Attack$`Attack Type`[i]
  not.fortinet.id <- is.na(as.numeric(attack.type))
  if (not.fortinet.id) {
    idsFinal_Attack$New[i] = attack.type
  } else {
    fortinet.url <- paste0(URL, attack.type)
    fortinet.page <- try(read_html(fortinet.url))
    if ("try-error" %in% class(fortinet.page)){
      idsFinal_Attack$New[i] <- NA
      next;
    }
    title <- fortinet.page %>%
      html_node(xpath = ".//*[@id='ency_title']") %>%
      html_text()
    title.clean <- gsub("^\\w+:\\s+", "", title)
    idsFinal_Attack$New[i] <- title.clean  
  }
}

【讨论】:

  • 是“read_tsv”函数应该重新创建我最初发布的“idsFinal_Attack”数据框吗?
  • 使用原始的 idsFinal_Attack 数据框,您的解决方案非常适用于映射到网页的所有 URL。但是,有一个 (fortinet.com/ids/VID127) 引发了以下错误:“open.connection(x, "rb") 中的错误:HTTP 错误 404。”。我认为原因是因为“找不到页面”。这发生在代码执行的中间,导致代码在剩余 80 行时停止执行。有没有办法解决这个问题,让代码继续运行,并且像“未解决”这样的消息被放置在网络数据应该去的单元格中?
  • 好电话。我添加了一个try 测试以查看read_html 是否失败,如果是,则使用NA 值填充New 列。这行得通吗?
  • 成功了!您的编码技术和描述性变量名称的使用是我需要努力的。绝对更具逻辑性和可读性。我最后担心的是以下行:html_node(xpath = ".//*[@id='ency_title']")。我读到 // 引用任何节点,并且 [@id=ency_title] 是具有属性名称的节点。但是,我无法理解 .和 *。此外,我通过右键单击网页的该部分并梳理 html 遇到了“id=ency_title”。是否有更快的方法来识别包含所需数据的节点?
  • 另外,我收到一条消息:警告消息:在运行代码大约 10 分钟后关闭未使用的连接 3 (fortinet.com/ids/VID127)。直到我运行另一段代码才出现。我应该在里面放一条线来关闭连接吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-06
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多