使用 dynamic/multiple 个 URL 抓取/抓取 R 数据
R data scraping / crawling with dynamic/multiple URLs
我试图在以下网址获取瑞士联邦最高法院的所有法令:https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=simple_query&query_words=&lang=de&top_subcollection_aza=all&from_date=&to_date=&x=12&y=12
不幸的是,没有提供 API。
我要检索的数据的 CSS 选择器是 .para
我知道 http://relevancy.bger.ch/robots.txt。
User-agent: *
Disallow: /javascript
Disallow: /css
Disallow: /hashtables
Disallow: /stylesheets
Disallow: /img
Disallow: /php/jurivoc
Disallow: /php/taf
Disallow: /php/azabvger
Sitemap: http://relevancy.bger.ch/sitemaps/sitemapindex.xml
Crawl-delay: 2
对我来说,我正在查看的 URL 似乎允许爬行,对吗?不管怎样,联邦法院解释说,这些规则是针对大型搜索引擎的,个人爬行是可以容忍的。
我可以检索单个法令的数据(使用 https://www.analyticsvidhya.com/blog/2017/03/beginners-guide-on-web-scraping-in-r-using-rvest-with-hands-on-knowledge/)
url <- 'https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=highlight_simple_query&page=1&from_date=&to_date=&sort=relevance&insertion_date=&top_subcollection_aza=all&query_words=&rank=1&azaclir=aza&highlight_docid=aza%3A%2F%2F18-12-2017-6B_790-2017&number_of_ranks=113971'
webpage <- read_html(url)
decree_html <- html_nodes(webpage,'.para')
rank_data <- html_text(decree_html)
decree1_data <- html_text(decree_html)
但是,由于 rvest 仅从一个特定页面提取数据,而我的数据在多个页面上,因此我尝试使用 Rcrawler 这样做(https://github.com/salimk/Rcrawler), but I do not know how to crawl the given site structur on www.bger.ch 以获取所有 URL 的法令。
我查看了以下帖子,但仍然找不到解决方案:
我不做下面的错误处理,因为那超出了这个问题的范围。
让我们从常见的嫌疑人开始:
library(rvest)
library(httr)
library(tidyverse)
我们将定义一个函数,该函数将按页码为我们获取一页搜索结果。自从您提供 URL.
以来,我已经对搜索参数进行了硬编码
在这个函数中,我们:
- 获取页面HTML
- 获取我们要抓取的文档的 links
- 获取文档元数据
- 制作数据框
- 为抓取的页码和是否有更多页面抓取的数据框添加属性
非常简单:
get_page <- function(page_num=1) {
GET(
url = "https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php",
query = list(
type="simple_query",
lang="de",
top_subcollection_aza="all",
query_words="",
from_date="",
to_date="",
x="12",
y="12",
page=page_num
)
) -> res
warn_for_status(res) # shld be "stop" and you should do error handling
pg <- content(res)
links <- html_nodes(pg, "div.ranklist_content ol li")
data_frame(
link = html_attr(html_nodes(links, "a"), "href"),
title = html_text(html_nodes(links, "a"), trim=TRUE),
court = html_text(html_nodes(links, xpath=".//a/../../div/div[contains(@class, 'court')]"), trim=TRUE), # these are "dangerous" if they aren't there but you can wrap error handling around this
subject = html_text(html_nodes(links, xpath=".//a/../../div/div[contains(@class, 'subject')]"), trim=TRUE),
object = html_text(html_nodes(links, xpath=".//a/../../div/div[contains(@class, 'object')]"), trim=TRUE)
) -> xdf
# this looks for the text at the bottom paginator. if there's no link then we're done
attr(xdf, "page") <- page_num
attr(xdf, "has_next") <- html_node(pg, xpath="boolean(.//a[contains(., 'Vorwärts')])")
xdf
}
制作一个辅助函数,因为我无法忍受打字 attr(...)
,它在使用中更易读:
has_next <- function(x) { attr(x, "has_next") }
现在,制作一个抓取循环。我刚好停在 6 点 b/c。您应该删除用于抓取所有内容的逻辑。考虑分批执行此操作,因为互联网连接不稳定:
pg_num <- 0
all_links <- list()
repeat {
cat(".") # poor dude's progress ber
pg_num <- pg_num + 1
pg_df <- get_page(pg_num)
if (!has_next(pg_df)) break
all_links <- append(all_links, list(pg_df))
if (pg_num == 6) break # this is here for me since I don't need ~11,000 documents
Sys.sleep(2) # robots.txt crawl delay
}
cat("\n")
将数据框列表变成一个大的。注意:您应该在此之前进行有效性测试,因为网络抓取充满了危险。您还应该将此数据框保存到 RDS 文件中,这样您就不必再次执行此操作。
lots_of_links <- bind_rows(all_links)
glimpse(lots_of_links)
## Observations: 60
## Variables: 5
## $ link <chr> "https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=highlight_simple_query&...
## $ title <chr> "18.12.2017 6B 790/2017", "14.12.2017 6G 2/2017", "13.12.2017 5A 975/2017", "13.12.2017 5D 257/2017", "...
## $ court <chr> "Strafrechtliche Abteilung", "Cour de droit pénal", "II. zivilrechtliche Abteilung", "II. zivilrechtlic...
## $ subject <chr> "Straf- und Massnahmenvollzug", "Procédure pénale", "Familienrecht", "Schuldbetreibungs- und Konkursrec...
## $ object <chr> "Bedingte Entlassung aus der Verwahrung, Beschleunigungsgebot", "Demande d'interprétation et de rectifi...
有了所有link,我们就去拿文件。
定义辅助函数。注意我们不在这里解析。分开做。我们将存储内部内容 <div>
HTML 文本,以便您稍后解析它。
get_documents <- function(urls) {
map_chr(urls, ~{
cat(".") # poor dude's progress ber
Sys.sleep(2) # robots.txt crawl delay
read_html(.x) %>%
xml_node("div.content") %>%
as.character() # we do this b/c we aren't parsing it yet but xml2 objects don't serialize at all
})
}
这是使用方法。同样,删除 head()
但也考虑分批进行。
head(lots_of_links) %>% # I'm not waiting for 60 documents
mutate(content = get_documents(link)) -> links_and_docs
cat("\n")
glimpse(links_and_docs)
## Observations: 6
## Variables: 6
## $ link <chr> "https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=highlight_simple_query&...
## $ title <chr> "18.12.2017 6B 790/2017", "14.12.2017 6G 2/2017", "13.12.2017 5A 975/2017", "13.12.2017 5D 257/2017", "...
## $ court <chr> "Strafrechtliche Abteilung", "Cour de droit pénal", "II. zivilrechtliche Abteilung", "II. zivilrechtlic...
## $ subject <chr> "Straf- und Massnahmenvollzug", "Procédure pénale", "Familienrecht", "Schuldbetreibungs- und Konkursrec...
## $ object <chr> "Bedingte Entlassung aus der Verwahrung, Beschleunigungsgebot", "Demande d'interprétation et de rectifi...
## $ content <chr> "<div class=\"content\">\n \n<div class=\"para\"> </div>\n<div class=\"para\">Bundesgericht </div>...
您仍然需要在各个地方进行错误和有效性检查,如果出现服务器错误或解析问题,可能需要重新抓取页面。但这是构建这种性质的特定于站点的爬虫的方法。
我试图在以下网址获取瑞士联邦最高法院的所有法令:https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=simple_query&query_words=&lang=de&top_subcollection_aza=all&from_date=&to_date=&x=12&y=12 不幸的是,没有提供 API。 我要检索的数据的 CSS 选择器是 .para
我知道 http://relevancy.bger.ch/robots.txt。
User-agent: *
Disallow: /javascript
Disallow: /css
Disallow: /hashtables
Disallow: /stylesheets
Disallow: /img
Disallow: /php/jurivoc
Disallow: /php/taf
Disallow: /php/azabvger
Sitemap: http://relevancy.bger.ch/sitemaps/sitemapindex.xml
Crawl-delay: 2
对我来说,我正在查看的 URL 似乎允许爬行,对吗?不管怎样,联邦法院解释说,这些规则是针对大型搜索引擎的,个人爬行是可以容忍的。
我可以检索单个法令的数据(使用 https://www.analyticsvidhya.com/blog/2017/03/beginners-guide-on-web-scraping-in-r-using-rvest-with-hands-on-knowledge/)
url <- 'https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=highlight_simple_query&page=1&from_date=&to_date=&sort=relevance&insertion_date=&top_subcollection_aza=all&query_words=&rank=1&azaclir=aza&highlight_docid=aza%3A%2F%2F18-12-2017-6B_790-2017&number_of_ranks=113971'
webpage <- read_html(url)
decree_html <- html_nodes(webpage,'.para')
rank_data <- html_text(decree_html)
decree1_data <- html_text(decree_html)
但是,由于 rvest 仅从一个特定页面提取数据,而我的数据在多个页面上,因此我尝试使用 Rcrawler 这样做(https://github.com/salimk/Rcrawler), but I do not know how to crawl the given site structur on www.bger.ch 以获取所有 URL 的法令。
我查看了以下帖子,但仍然找不到解决方案:
我不做下面的错误处理,因为那超出了这个问题的范围。
让我们从常见的嫌疑人开始:
library(rvest)
library(httr)
library(tidyverse)
我们将定义一个函数,该函数将按页码为我们获取一页搜索结果。自从您提供 URL.
以来,我已经对搜索参数进行了硬编码在这个函数中,我们:
- 获取页面HTML
- 获取我们要抓取的文档的 links
- 获取文档元数据
- 制作数据框
- 为抓取的页码和是否有更多页面抓取的数据框添加属性
非常简单:
get_page <- function(page_num=1) {
GET(
url = "https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php",
query = list(
type="simple_query",
lang="de",
top_subcollection_aza="all",
query_words="",
from_date="",
to_date="",
x="12",
y="12",
page=page_num
)
) -> res
warn_for_status(res) # shld be "stop" and you should do error handling
pg <- content(res)
links <- html_nodes(pg, "div.ranklist_content ol li")
data_frame(
link = html_attr(html_nodes(links, "a"), "href"),
title = html_text(html_nodes(links, "a"), trim=TRUE),
court = html_text(html_nodes(links, xpath=".//a/../../div/div[contains(@class, 'court')]"), trim=TRUE), # these are "dangerous" if they aren't there but you can wrap error handling around this
subject = html_text(html_nodes(links, xpath=".//a/../../div/div[contains(@class, 'subject')]"), trim=TRUE),
object = html_text(html_nodes(links, xpath=".//a/../../div/div[contains(@class, 'object')]"), trim=TRUE)
) -> xdf
# this looks for the text at the bottom paginator. if there's no link then we're done
attr(xdf, "page") <- page_num
attr(xdf, "has_next") <- html_node(pg, xpath="boolean(.//a[contains(., 'Vorwärts')])")
xdf
}
制作一个辅助函数,因为我无法忍受打字 attr(...)
,它在使用中更易读:
has_next <- function(x) { attr(x, "has_next") }
现在,制作一个抓取循环。我刚好停在 6 点 b/c。您应该删除用于抓取所有内容的逻辑。考虑分批执行此操作,因为互联网连接不稳定:
pg_num <- 0
all_links <- list()
repeat {
cat(".") # poor dude's progress ber
pg_num <- pg_num + 1
pg_df <- get_page(pg_num)
if (!has_next(pg_df)) break
all_links <- append(all_links, list(pg_df))
if (pg_num == 6) break # this is here for me since I don't need ~11,000 documents
Sys.sleep(2) # robots.txt crawl delay
}
cat("\n")
将数据框列表变成一个大的。注意:您应该在此之前进行有效性测试,因为网络抓取充满了危险。您还应该将此数据框保存到 RDS 文件中,这样您就不必再次执行此操作。
lots_of_links <- bind_rows(all_links)
glimpse(lots_of_links)
## Observations: 60
## Variables: 5
## $ link <chr> "https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=highlight_simple_query&...
## $ title <chr> "18.12.2017 6B 790/2017", "14.12.2017 6G 2/2017", "13.12.2017 5A 975/2017", "13.12.2017 5D 257/2017", "...
## $ court <chr> "Strafrechtliche Abteilung", "Cour de droit pénal", "II. zivilrechtliche Abteilung", "II. zivilrechtlic...
## $ subject <chr> "Straf- und Massnahmenvollzug", "Procédure pénale", "Familienrecht", "Schuldbetreibungs- und Konkursrec...
## $ object <chr> "Bedingte Entlassung aus der Verwahrung, Beschleunigungsgebot", "Demande d'interprétation et de rectifi...
有了所有link,我们就去拿文件。
定义辅助函数。注意我们不在这里解析。分开做。我们将存储内部内容 <div>
HTML 文本,以便您稍后解析它。
get_documents <- function(urls) {
map_chr(urls, ~{
cat(".") # poor dude's progress ber
Sys.sleep(2) # robots.txt crawl delay
read_html(.x) %>%
xml_node("div.content") %>%
as.character() # we do this b/c we aren't parsing it yet but xml2 objects don't serialize at all
})
}
这是使用方法。同样,删除 head()
但也考虑分批进行。
head(lots_of_links) %>% # I'm not waiting for 60 documents
mutate(content = get_documents(link)) -> links_and_docs
cat("\n")
glimpse(links_and_docs)
## Observations: 6
## Variables: 6
## $ link <chr> "https://www.bger.ch/ext/eurospider/live/de/php/aza/http/index.php?lang=de&type=highlight_simple_query&...
## $ title <chr> "18.12.2017 6B 790/2017", "14.12.2017 6G 2/2017", "13.12.2017 5A 975/2017", "13.12.2017 5D 257/2017", "...
## $ court <chr> "Strafrechtliche Abteilung", "Cour de droit pénal", "II. zivilrechtliche Abteilung", "II. zivilrechtlic...
## $ subject <chr> "Straf- und Massnahmenvollzug", "Procédure pénale", "Familienrecht", "Schuldbetreibungs- und Konkursrec...
## $ object <chr> "Bedingte Entlassung aus der Verwahrung, Beschleunigungsgebot", "Demande d'interprétation et de rectifi...
## $ content <chr> "<div class=\"content\">\n \n<div class=\"para\"> </div>\n<div class=\"para\">Bundesgericht </div>...
您仍然需要在各个地方进行错误和有效性检查,如果出现服务器错误或解析问题,可能需要重新抓取页面。但这是构建这种性质的特定于站点的爬虫的方法。