在R搜寻后抓取asp javascript分页表格

时间:2018-08-10 21:46:31

标签: javascript r web-scraping rvest rselenium

我正在尝试使用rvestRSelenium提取https://www.askebsa.dol.gov/epds/default.asp上的内容,但是在javascript页面以搜索框开头时找不到指导吗?最好将所有这些内容都放入一个简单的CSV文件中。

在那之后,从https://www.askebsa.dol.gov/mewaview/View/Index/6219之类的个人文件中提取数据似乎是可能的。谢谢

3 个答案:

答案 0 :(得分:2)

对于问题的第一部分,使用rvest的方法应该有效。我在最后一步收到一个错误,找不到所需的名称标签。

这是我的方法-

# open a html-session
web_session <- html_session("https://www.askebsa.dol.gov/epds/default.asp")
# get the form
test_search <- html_form(read_html("https://www.askebsa.dol.gov/epds/default.asp"))[[2]]

# set the required values for fields such as company_name, ein_number etc
# pass that info and submit the form - here i am getting an error 
# it cannot recognize the 'search button' name 
# if that is resolved it should work
set_values(test_search, 'm1company' = "Bend", 'm1ein' = '81-6268978' ) %>%
  submit_form(web_session, ., submit = "cmdSubmitM1") %>%
  read_html(.) -> some_html

如果我有时间,我会尝试做更多的研究,然后再回覆您。我发现了一些关于类似主题herehere的教程和相关问题。它们有些旧,但仍然有用。

对于第二部分,由于您没有涉及任何动态元素,因此更容易。我可以使用“ selector-gadget”检索表单中的所有地址,并将所有节点名称复制粘贴到html_nodes()函数中。

# read the file and save it into a nested list
test_file_with_address <- read_html("https://www.askebsa.dol.gov/mewaview/View/Index/6219")

# copy paste all the css node names and get the text from the html file
test_file_with_address %>%
  html_nodes(".border-top:nth-child(19) code , .border-top:nth-child(18) code , .border-top:nth-child(14) code , .border-top:nth-child(13) code , .border-top:nth-child(12) code , .border-top:nth-child(11) code , .border-top:nth-child(9) code , .section-header+ .border-top code
") %>% html_text()

[1] "\r\n                Bend Chamber of Commerce Benefit Plan and Trust for Wood Products Employers\r\n                777 N.W. Wall Street, Suite 200\r\n                Bend,  OR  97703\r\n                \r\n                "
 [2] "(541) 382-3221"                                                                                                                                                                                                                
 [3] "81-6268978"                                                                                                                                                                                                                    
 [4] "501"                                                                                                                                                                                                                           
 [5] "\r\n                Bend Chamber of Commerce\r\n                777 N.W. Wall Street, Suite 200\r\n                Bend,  OR  97703\r\n                \r\n                "                                                   
 [6] "(541) 382-3221"                                                                                                                                                                                                                
 [7] "93-0331932"                                                                                                                                                                                                                    
 [8] "\r\n                Katy Brooks\r\n                Bend Chamber of Commerce\r\n                777 N.W. Wall Street, Suite 200\r\n                Bend,  OR  97703\r\n                \r\n                "                    
 [9] "(541) 382-3221"                                                                                                                                                                                                                
[10] "katy@bendchamber.org"                                                                                                                                                                                                          
[11] "\r\n                Deb Oster\r\n                Scott Logging/Scott Transportation\r\n                400 S.W. Bluff Drive, #101\r\n                Bend,  OR  97702\r\n                \r\n                "                 
[12] "(541) 536-3636"                                                                                                                                                                                                                
[13] "debo@scotttransport.com"                                                                                                                                                                                                       
[14] "\r\n                Karen Gibbons\r\n                Allen & Gibbons Logging\r\n                P.O. Box 754\r\n                Canyonville,  OR  97417\r\n                \r\n                "                               
[15] "(541) 839-4294"                                                                                                                                                                                                                
[16] "agibbonslog@frontiernet.net"                                                                                                                                                                                                   
[17] "\r\n                Cascade East Benefits\r\n                dba Johnson Benefit Planning\r\n                777 N.W. Wall Street, Suite 100\r\n                Bend,  OR  97703\r\n                \r\n                "      
[18] "(541) 382-3571"                                                                                                                                                                                                                
[19] "del@johnsonbenefitplanning.com"                                                                                                                                                                                                
[20] "93-1130374"                                                                                                                                                                                                                    
[21] "\r\n                PacificSource Health Plans\r\n                P.O. Box 7068\r\n                Springfield,  OR  97475-0068\r\n                \r\n                "                                                       
[22] "(541) 686-1242"                                                                                                                                                                                                                
[23] "george.sherwood@pacifcsource.com"                                                                                                                                                                                              
[24] "93-0245545"                                                                                                                                                                                                                    
[25] "\r\n                PacificSource Health Plans\r\n                P.O. Box 7068\r\n                Springfield,  OR  97475-0068\r\n                \r\n                "                                                       
[26] "(541) 686-1242"                                                                                                                                                                                                                
[27] "george.sherwood@pacificsource.com"                                                                                                                                                                                             
[28] "93-0245545"                                                                                                                                                                                                                    
[29] "N/A"

这需要更多regex的魔法来清理并将它们放入data.frame中,但是基本的构造块还是可以看到的。

答案 1 :(得分:2)

以下是使用RSelenium来获取指向各个文件的链接的示例。检索链接后,其余部分应该很简单。您可以使用rvest导航到这些URL(如前所述),并借助诸如stringr之类的字符串操作工具来解析内容。对于第二部分,期望所有形式的系统结构都是乐观的。请尝试花费一些时间来构造特定的regular expression,以便从检索到的文本中提取所需的内容。

下面的代码不一定是解决问题的最有效方法,但它包含正确的RSelenium概念和思想。随时根据需要进行调整。

其他信息:RSelenium: Basics

# devtools::install_github("ropensci/RSelenium")
library(RSelenium)

# launch a remote driver 
driver <- rsDriver(browser=c("chrome"))
remDr <- driver[["client"]]

# select an URL
url <- "https://www.askebsa.dol.gov/epds/default.asp"

# navigate to the URL
remDr$navigate(url)

# choose year - option[2] corresponds to 2017
year <- remDr$findElements(using = 'xpath',  '//*[@id="m1year"]/option[2]')
year[[1]]$clickElement()

# choose company
company <- remDr$findElements(using = 'xpath',  '//*[@id="m1company"]')
company[[1]]$sendKeysToElement(list("Bend"))

# enter ein
ein <- remDr$findElements(using = 'xpath',  '//*[@id="m1ein"]')
ein[[1]]$sendKeysToElement(list("81-6268978"))

# sumbit the form to get the results
submit <- remDr$findElements(using = 'xpath',  '//*[@id="cmdSubmitM1"]')
submit[[1]]$clickElement()

# get the total number of results
num_of_results <- remDr$findElements(using = 'xpath',  '//*[@id="block-system-main"]/div/div/div/div/div/div[1]/form/table[1]/tbody/tr/td/div/b[1]')
n <- as.integer(num_of_results[[1]]$getElementText()[[1]])

# loop through results and print the links
for(i in 1:n) {
  xpath <- paste0('//*[@id="block-system-main"]/div/div/div/div/div/div[1]/form/table[3]/tbody/tr[', i + 1, ']/td[1]/a')
  link <- remDr$findElements('xpath', xpath)
  print(link[[1]]$getElementAttribute('href'))
}

# [[1]]
# [1] "https://www.askebsa.dol.gov/mewaview/View/Index/5589"
# 
# [[1]]
# [1] "https://www.askebsa.dol.gov/mewaview/View/Index/6219"

请注意,如果不缩小搜索范围,您将获得50多个结果,因此将获得一页以上的结果。在这种情况下,您需要对代码进行其他调整(for循环中xpath的结构可能会更改,您可能需要导航至其他页面,循环应限于50次迭代等)。

我相信这可以解决您的实际问题,即动态抓取。您可能需要单独发布后续问题,因为它们包含不同的概念。只要您使用合适的标签在另一个问题中解决此特定问题,就有很多regex专家会帮助您解析这些表格。

答案 2 :(得分:1)

为了获得结果,您必须填写表格并提交。您可以通过检查html找到url和字段名称。

$this->data['users'] = $this->Ion_auth->usersdata();

foreach($this->data['users'] as $list){
    $data[] = array(
        'id' =>$list->id,
        'email' => $list->email,
        'username' => $list->username,
        'active' => $list->active
    );
}

$this->data['userslist'] = $data;
$this->render('users/users_list','public_master');

现在我们可以提交表格并收集链接。我们可以使用此选择器url <- "https://www.askebsa.dol.gov/epds/m1results.asp" post_data <- list( m1year = 'ALL', # Year m1company = '', # Name of MEWA (starts with) m1ein = '', # EIN m1state = 'ALL', # State of MEWA Headquarters m1coverage = 'ALL', # State(s) where MEWA offers coverage m1filingtype = 'ALL', # Type of filing cmdSubmitM1 = 'Search', # hidden fields auth = 'Y', searchtype = 'Q', sf = 'EIN', so = 'A' ) 抓取链接。

table.table.table-condensed td a

这将产生首页的所有链接。

检查HTTP流量我注意到通过提交带有一些额外字段(m1formid,allfilings,页面)的相同表单来加载下一页。我们可以通过循环增加页面值来获取下一页。

html <- read_html(POST(url, body = post_data, encode = "form"))
links <- html_nodes(html, 'table.table.table-condensed td a') %>% html_attr("href") 
links <- paste0("https://www.askebsa.dol.gov", links) 

对于问题的第二部分,我假设目标是选择表单项及其值。您可以通过选择所有library(httr) library(rvest) url <- "https://www.askebsa.dol.gov/epds/m1results.asp" post_data <- list( m1year='ALL', m1company='', m1ein='', m1state='all', m1coverage='all', m1filingtype='ALL', cmdSubmitM1 = 'Search', auth='Y', searchtype='Q', sf='EIN', so='A', m1formid='', allfilings='', page=1 ) links = list() while (TRUE) { html <- read_html(POST(url, body = post_data, encode = "form")) page_links <- html_nodes(html, 'table.table.table-condensed td a') %>% html_attr("href") %>% paste0("https://www.askebsa.dol.gov/", .) links <- c(links, page_links) last <- html_text(tail(html_nodes(html, 'div.textnorm > a'), n=2)[1]) if (last != 'Last') { break } post_data['page'] <- post_data[['page']] + 1 } print(links) 标签和每个项目的下一个div.question-inline标签来做到这一点。

code

此代码将生成包含所有表单项的命名列表,但可以对其进行修改以生成嵌套列表或更合适的结构。
在这一点上,我必须说我对R的经验很少,因此该代码可能不是一个好的编码示例。任何提示或其他评论都非常欢迎。