R 中的 Tabulizer 包:如何在特定标题后抓取表格

Tabulizer package in R: how to scrape tables after specific Title

如何从 PDF 中抓取 table 开头的一些标题文本? 我正在试验 tabulizer 包。这是一个从 specific 页面获取 table 的示例(波兰语 "Map of Public Health Needs")

library(tabulizer)
library(tidyverse)
options(java.parameters = "-Xmx8000m")

location<-"http://www.mpz.mz.gov.pl/wp-content/uploads/sites/4/2019/01/mpz_choroby_ukladu_kostno_miesniowego_woj_dolnoslaskie.pdf"

(out<-extract_tables(location, pages = 8,encoding = "UTF-8", method = "stream", outdir = getwd())[[4]] %>%
as.tibble())

这让我在 specific 页面上得到了一个 table。但是我会有很多这样的 pdf 可以从网站上抓取:http://www.mpz.mz.gov.pl/mapy-dla-30-grup-chorob-2018/ 然后是包含每种疾病的许多链接的子页面,获取与 rvest 的链接,对于波兰的每个省,我需要抓取 tables 在 specific 标题字符串之后,例如。

Tabela 1.2.2: Struktura zapadalnosci rejestrowanej w zależności od płci, miejsca zamieszkania oraz groupy wiekowej - Choroby układowe tkanki łącznej"

我需要检测 Tabela(...) Struktura zapadalnosci(...)",因为 tables 可能不在同一页上。非常感谢任何指示和想法。

编辑:在我提出这个问题之后,我到目前为止成功地找到了 table 可能所在的页面,也许非常无效:

library(pdfsearch)

pages <-
  keyword_search(
    location,
    keyword = c(
      'Tabela',
      'Struktura zapadalnosci rejestrowanej'
    ),
    path = TRUE,
    surround_lines = FALSE
  ) %>%
  group_by(page_num) %>%
  mutate(keyword = paste0(keyword, collapse = ";")) %>%
  filter(
    str_detect(keyword, "Tabela") &
      str_detect(keyword, "Struktura zapadalnosci rejestrowanej")
  ) %>%
  pull(page_num) %>%
  unique()

你应该试试 Rcrawler

其主要 Rcrawler 功能似乎是专门为满足您的需要而设计的 - 其 KeywordsFilter 参数:

KeywordsFilter  

character vector,适用于只希望抓取或收集包含一个或多个关键字的网页的用户。 Rcrawler 根据创建的关键词数量计算准确率。此参数必须是一个向量,其中至少有一个关键字,例如 c("mykeyword").

我可以帮助你解决你的基本问题,但有一个问题(见最后)。我使用 pdftools 而不是 pdfsearch 但在这种情况下它基本上做同样的事情(查找带有 table 的页面)。为了节省时间,我一开始只下载了一次PDF:

options(java.parameters = "-Xmx8000m")# needs to be set before loading tabulizer
library(tabulizer)
library(tidyverse)

location <- "http://www.mpz.mz.gov.pl/wp-content/uploads/sites/4/2019/01/mpz_choroby_ukladu_kostno_miesniowego_woj_dolnoslaskie.pdf"
download.file(location, "test.pdf", mode = "wb")

现在将 pdf 转换为 data.frame,每行在 df 的一行中:

raw <- pdftools::pdf_data("test.pdf") 
pages <- lapply(seq_along(raw), function(p) {
  if (nrow(raw[[p]]) > 0) {
    raw[[p]]$page <- p
    raw[[p]]
  }
}) %>% 
  bind_rows() %>% 
  group_by(y, page) %>% 
  summarise(text = paste(text, collapse = " ")) %>% 
  arrange(page, y)

此 data.frame 是可搜索的,我们只保留符合您关键字的行:

tables <- pages %>% 
  filter(grepl("Tabela .* Struktura zapadalnosci", text))

有 8 行符合关键字。我们只从中提取 tables。此外,lapply 循环中的函数只保留行数最多的矩阵。如果一页上有两个 table 可能是个问题,但通常只使用 tabulizer 找到 table 结构的 'best guess' 效果很好。

tables_list <- lapply(tables$page, function(p) {
  cat(p, "\n")
  out <- extract_tables("test.pdf", 
                        pages = p,
                        encoding = "UTF-8", 
                        method = "stream", 
                        output = "matrix")
  out <- as_tibble(out[[which.max(sapply(out, nrow) + sapply(out, ncol))]]) # keep the biggest table
  attr(out, "caption") <- tables$text[tables$page %in% p]
  return(out)
})

object tables_list 现在包含 data.frames 的列表,每一个转换为 table:

> tables_list[[1]]
# A tibble: 16 x 8
   V1                  V2    V3    V4    V5    V6    V7    V8   
   <chr>               <chr> <chr> <chr> <chr> <chr> <chr> <chr>
 1 dolnośląskie        77,05 74,65 4,04  10,59 13,37 27,87 44,14
 2 kujawsko-pomorskie  78,12 65,93 4,29  14,96 14,82 27,01 38,92
 3 lubelskie           76,50 56,83 2,67  14,83 17,00 29,00 36,50
 4 lubuskie            79,10 76,23 4,92  12,70 12,70 30,74 38,93
 5 łódzkie             74,37 67,77 6,45  13,84 15,09 30,03 34,59
 6 małopolskie         72,71 55,35 6,99  14,63 12,01 25,87 40,50
 7 mazowieckie         76,31 68,52 5,89  12,11 12,30 27,03 42,67
 8 opolskie            79,55 54,65 4,83  10,04 17,47 26,02 41,64
 9 podkarpackie        75,10 47,32 7,57  14,86 18,29 25,31 33,98
10 podlaskie           74,18 68,00 5,82  10,55 17,09 32,36 34,18
11 pomorskie           76,57 74,96 5,71  12,74 13,76 26,65 41,14
12 śląskie             73,51 81,15 4,89  14,96 14,43 26,64 39,08
13 świętokrzyskie      74,45 56,51 4,91  14,00 14,74 27,27 39,07
14 warmińsko-mazurskie 75,91 63,22 5,62  13,59 18,48 29,53 32,79
15 wielkopolskie       72,66 62,71 3,62  14,37 14,77 29,45 37,79
16 zachodniopomorskie  74,26 73,21 8,44  13,71 11,60 24,89 41,35

我还添加了每个 table 的(第一行)标题作为 data.frame 的属性:

> attr(tables_list[[1]], "caption")
[1] "Tabela 1.2.2: Struktura zapadalnosci rejestrowanej w zależności od płci, miejsca zamieszkania oraz grupy"

将此与 pdf 进行比较:

这看起来效果不错,只是列名不见了。不确定是否有办法保留它们,但您的问题中没有包含该方法,所以也许您已经有了解决方案?