使用下拉菜单中的选项从结果页面下载CSV文件



我是使用 R进行网页抓取的新手,我遇到了这个问题:我想使用 R 向 PubMed 提交搜索查询,然后从结果页面下载 CSV 文件。可以通过单击"发送到"来访问CSV文件,这将打开一个下拉菜单,然后我需要选择"文件"单选按钮,将"格式"选项更改为"CSV"(选项6),最后单击"创建文件"按钮开始下载。

一些注意事项:
1.是的,这种类型的远程搜索和下载符合NCBI的政策。
2. 为什么不使用easyPubMed包?我已经尝试过这个,并将其用于我工作的另一部分。但是,使用此包检索搜索结果会错过 CSV 下载包含的一些文章元数据。

我查看了这些相关问题:使用 R 中的 rvest 包从下拉列表中提交表单后从网页下载 csv 文件,R 下载绑定到输入框和"单击"按钮.csv文件,使用 R "单击"网页上的下载文件按钮。

我觉得@hrbrmstr之前提供的解决方案包含答案,但我只是无法将这些碎片放在一起下载CSV文件。

我认为这个问题的优雅解决方案是一个两步过程:1) 向 PubMedPOST搜索请求并GET结果,以及 2) 向结果页面提交第二个POST请求(或以某种方式在其中导航),并选择所需的选项来下载 CSV 文件。我已经尝试了以下玩具搜索查询("hello world",带引号,目前返回 6 个结果)......

query <- '"hello world"'
url <- 'https://www.ncbi.nlm.nih.gov/pubmed/'
html_form(html_session(url)) # enter query using 'term'
# post search and retrieve results
session <- POST(url,body = list(term=query),encode='form')
# scrape results to check that above worked
content(session) %>% html_nodes('#maincontent > div > div:nth-child(5)') %>% 
html_text()
content(session) %>% html_nodes('#maincontent > div > div:nth-child(5)') %>% 
html_nodes('p') %>% html_text()
# view html nodes of dropdown menu -- how to 'click' these via R?
content(session) %>% html_nodes('#sendto > a')
content(session) %>% html_nodes('#send_to_menu > fieldset > ul > li:nth-child(1) > label')
content(session) %>% html_nodes('#file_format')
content(session) %>% html_nodes('#submenu_File > button')
# submit request to download CSV file
POST(session$url, # I know this doesn't work, but I would hope something similar is possible
encode='form',
body=list('EntrezSystem2.PEntrez.PubMed.Pubmed_ResultsPanel.Pubmed_DisplayBar.SendTo'='File',
'EntrezSystem2.PEntrez.PubMed.Pubmed_ResultsPanel.Pubmed_DisplayBar.FFormat'=6,
'EntrezSystem2.PEntrez.PubMed.Pubmed_ResultsPanel.Pubmed_DisplayBar.SendToSubmit'=1),
write_disk('results.csv'))

上面的最后一行失败 - 下载了一个 CSV 文件,但它包含来自 POST 请求的 html 结果。理想情况下,如何编辑最后一行以获取所需的 CSV 文件?

一个可能的黑客直接跳到结果页面。换句话说,我知道提交"hello world"搜索会返回以下URL:https://www.ncbi.nlm.nih.gov/pubmed/?term=%22hello+world%22。因此,如有必要,我可以从这里推断并根据我的搜索查询构建结果 URL。

我尝试将此 URL 插入上面的行,但它仍然没有返回所需的 CSV 文件。我可以使用以下命令查看表单字段...

# view form options on the results page
html_form(html_session('https://www.ncbi.nlm.nih.gov/pubmed/?term=%22hello+world%22'))

或者,我可以在知道上述表单选项的情况下扩展 URL 吗?像...

url2 <- 'https://www.ncbi.nlm.nih.gov/pubmed/?term=%22hello+world%22&EntrezSystem2.PEntrez.PubMed.Pubmed_ResultsPanel.Pubmed_DisplayBar.SendTo=File&EntrezSystem2.PEntrez.PubMed.Pubmed_ResultsPanel.Pubmed_DisplayBar.FFormat=6&EntrezSystem2.PEntrez.PubMed.Pubmed_ResultsPanel.Pubmed_DisplayBar.SendToSubmit=1'
POST(url2,write_disk('results2.csv'))

我希望下载一个包含 6 个包含文章元数据的结果的 CSV 文件,但是,我正在获取结果页面的 html。

任何帮助将不胜感激!谢谢。

如果我将您的问题重新定义为:"我想使用 R 向 PubMed 提交搜索查询,然后下载与结果页面上CSV 下载选项中提供的信息相同的信息

然后,我认为您可以跳过抓取和Web UI自动化,直接转到NIH为此目的提供的API。

此 R 代码的第一部分执行相同的搜索("hello world"),并以 JSON 格式获得相同的结果(随意将search_url链接粘贴到浏览器中进行验证)。

library(httr)
library(jsonlite)
library(tidyverse)
# Search for "hello world"
search_url <- "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=%22hello+world%22&format=json"
# Search for results
search_result <- GET(search_url)
# Extract the content
search_content <- content(search_result, 
type = "application/json",
simplifyVector = TRUE)
# search_content$esearchresult$idlist
# [1] "29725961" "28103545" "27567633" "25955529" "22999052" "19674957"
# Get a vector of the search result IDs
result_ids <- search_content$esearchresult$idlist
# Get a summary for id 29725961 (the first one).
summary_url <- "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&version=2.0&id=29725961&format=json" # 
summary_result <- GET(summary_url)
# Extract the content
summary_content <- content(summary_result, 
type = "application/json")

据推测,您可以从这里获取它,因为列表summary_content包含您需要的信息,只是格式不同(我通过目视检查进行了验证)。

但是,为了符合您原始问题的精神(通过从NCBI中提取R,使用R进行CSV),您可以使用以下一些步骤来重现与人类PubMed Web UI完全相同的CSV。

# Quickie cleanup (thanks to Tony ElHabr)
# https://www.r-bloggers.com/converting-nested-json-to-a-tidy-data-frame-with-r/
summary_untidy <- enframe(unlist(summary_content))
# Get rid of *some* of the fluff...
summary_tidy <- summary_untidy %>% 
filter(grepl("result.29725961", name)) %>% 
mutate(name = sub("result.29725961.", "", name))
# Convert the multiple author records into a single comma-separated string.
authors <- summary_tidy %>% 
filter(grepl("^authors.name$", name)) %>% 
summarize(pasted = paste(value, collapse = ", "))
# Begin to construct a data frame that has the same information as the downloadable CSV
summary_csv <- tibble(
Title = summary_tidy %>% filter(name == "title") %>% pull(value),
URL = sprintf("/pubmed/%s", summary_tidy %>% filter(name == "uid") %>% pull(value)),
Description = pull(authors, pasted),
Details = "... and so on, and so on, and so on... "
)
# Write the sample data frame to a csv.
write_csv(summary_csv, path = "just_like_the_search_page_csv.csv")

我不熟悉你提到的easyPubMed包,但我通过挖掘easyPubMed代码而受到启发,使用 NCBI API。 您完全有可能修复/调整一些easyPubMed代码,以提取您希望从拉取一堆CSV中获得的其他元数据。 (那里没有很多。 只有 500 行代码定义了 8 个函数。

哎呀,如果您确实设法调整 easyPubMed 代码以提取其他元数据,我建议您将您的更改返回给作者,以便他们可以改进他们的软件包!

使用 easyPubMed 软件包:

library(easyPubMed)
out <- batch_pubmed_download(pubmed_query_string = "hello world")
DF <- table_articles_byAuth(pubmed_data = out[1])
write.csv(DF, "helloworld.csv")

有关详细信息,请参阅easyPubMed中的小插图和帮助文件。

其他软件包包括 pubmed.mineR、rentrez 和 RISmed on CRAN、Bioconductor 上的注释和 github 上的 Rcupcake。

最新更新