R網頁抓取資料
R網頁抓取資料
web上有大量可用的資料。其中一些是以格式化的、可下載的data-sets的形式,易於訪問。但大多數線上資料都是作為網路內容存在的,如部落格、新聞故事和烹飪菜譜。使用格式化的檔案,訪問資料相當簡單;只需下載檔案,必要時解壓縮,然後匯入到r。
然而,對於“wild”資料,將資料轉換成可分析的格式更困難。訪問此類的線上資料有時稱為“web抓取”。您將需要從網際網路下載目標頁面並提取您需要的資訊。兩個r工具,從基本包中的readline ( )和rcurl包中的geturl ()使此任務成為可能。
Readlines
對於基本的web抓取任務,readline ()函式通常就足夠了。readline ()web_page <- readLines("http://www.interestingwebsite.com")
作為一個(有點)實際使用web抓取的例子,設想一個場景,我們想知道2009年1月的r -help伺服器上的10個最常見的海報。因為伺服器是在一個安全的站點上(例如,它有https : / /而不是http : / /在URL中),我們不能輕鬆地使用readline ()訪問live版本。因此,對於此示例,我已在此站點上釋出了列表歸檔的本地副本。
readline ()其本身只能獲取資料。您將需要使用
web_page <- read.csv("http://www.programmingr.com/jan09rlist.html") author_lines <- web_page[grep("<I>", web_page)] authors <- gsub("<I>", "", author_lines, fixed = TRUE) author_counts <- sort(table(authors), decreasing = TRUE) author_counts[1:10]
為了理解為什麼這個示例如此簡單,下面是對底層html的更深入的瞭解:
老實說,這是關於使用者友好,因為您可以得到的html資料格式的“在野外”。我們感興趣的資料元素(海報名稱)是它自己行的主要元素。我們可以使用grep ()快速輕鬆地獲取這些行。一旦我們有了我們感興趣的行,我們可以通過使用gsub ()來替換不需要的html程式碼。
順便說一句,對於那些也是web開發人員的人來說,這可能是重複任務的一個巨大的節省時間。如果您沒有處理任何高度敏感的問題,請向您的站點新增一些簡單的“資料轉儲”頁面,並使用readline ()在您需要的時候撤回資料。這對於進度報告和狀態更新非常重要。確保頁面設計簡單——基本的、格式良好的html和最小的絨毛。
在找一個測試專案嗎?檢視我們的網頁抓取專案的想法!
rcurl包
為了獲得更高階的http功能(如post功能和https訪問),您需要使用rcurl包。要使用rcurl包執行web抓取任務,請使用geturl ()函式。在通過geturl ()獲取資料之後,需要對它進行重組和解析。XML包中的htmltreeparse ()函式是專門為這個任務定製的。使用geturl ()我們可以訪問一個安全的站點,因此我們可以使用實時站點作為示例。# Install the RCurl package if necessary
install.packages("RCurl", dependencies = TRUE)
library("RCurl")
# Install the XML package if necessary
install.packages("XML", dependencies = TRUE)
library("XML")
# Get first quarter archives
jan09 <- getURL("https://stat.ethz.ch/pipermail/r-help/2009-January/date.html", ssl.verifypeer = FALSE)
jan09_parsed <- htmlTreeParse(jan09)
對於基本的web抓取任務readline ()將足夠並避免使任務複雜化。對於更困難的程式或需要其他http功能geturl ()或rcurl包中的其他功能的任務,可能需要。這是我們在網上抓取的系列中的第一個。請檢視後面的一篇文章,瞭解有關抓取的更多資訊:
1.json
json已經成為在web上共享資料的通用標準之一,特別是可能被前端JavaScript應用程式使用的資料。json ( JavaScriptobject符號)是一個關鍵的:值格式,它為讀者提供了一個關於價值的含義的高度的上下文。鍵-值結構可以巢狀,允許如下資料分組:
{‘book’:”Midsummer Nights Dream”,
‘author’: “William Shakespeare”,
‘price’:5.99,
‘inventory’:12}
對於已經出現了幾個用於r使用者的庫,使您能夠輕鬆地處理和消化json資料。我們將從其中一個庫jsonlite提供一個示例,它是另一個領先庫rjsonio的分叉。我們選擇了這個圖書館,由於它的相對易用性。我們從預賽開始,因為jsonlite不作為r標準庫的一部分:
json_file <- "https://jsonplaceholder.typicode.com/posts"
data <- fromJSON(json_file)
我們將使用一個用於JSON資料的佔位符生成器:https : / / www . jsonplaceholder.typicode.com . org/帖子.這個服務列出了一個錯誤的JSON資料列表,據稱是一個部落格文章或新聞文章的列表。將這些資訊移動到r資料幀相當簡單。它為我們提供了一個具有要求的欄位的可愛的資料幀。對於喜歡在文字編輯器或excel中瀏覽資料的人,您可以輕鬆地將檔案轉儲到CSV檔案,並使用以下一個線性檔案:該包可以支援更高階的資料檢索,包括:
訪問需要金鑰的API;提取並連線到單個數據幀中的多頁劃痕;使用複雜的標頭和資料元素的post請求操作;這裡詳細介紹了一組示例(由包作者提供)。
本節列出了以JSON格式釋出資料的公共httpAPI的一些示例。這些是很好的,以瞭解在真實的世界JSON資料中遇到的複雜結構。所有服務都是免費的,但有些服務需要註冊/身份驗證。每個示例返回大量資料,因此不是所有輸出都在本文件中列印。
library(jsonlite)
github
github是一個線上程式碼儲存庫,並具有幾乎所有活動的APIs來獲取實時資料。下面是一個著名的r包和作者的一些例子:
hadley_orgs <- fromJSON("https://api.github.com/users/hadley/orgs")
hadley_repos <- fromJSON("https://api.github.com/users/hadley/repos")
gg_commits <- fromJSON("https://api.github.com/repos/hadley/ggplot2/commits")
gg_issues <- fromJSON("https://api.github.com/repos/hadley/ggplot2/issues")
#latest issues
paste(format(gg_issues$user$login), ":", gg_issues$title)
[1] "jsta : fix broken stowers link"
[2] "krlmlr : Log transform on geom_bar() silently omits layer"
[3] "yutannihilation : Fix a broken link in README"
[4] "raubreywhite : Fix theme_gray's legend/panels for large base_size"
[5] "batuff : Add minor ticks to axes"
[6] "mcol : overlapping boxes with geom_boxplot(varwidth=TRUE)"
[7] "karawoo : Fix density calculations for groups with one or two elements" [8] "Thieffen : fix typo"
[9] "Thieffen : fix typo"
[10] "thjwong : `axis.line` works, but not `axis.line.x` and `axis.line.y`"
[11] "schloerke : scale_discrete not listening to 'breaks' arg"
[12] "hadley : Consider use of vwline"
[13] "JTapper : geom_polygon accessing data$y"
[14] "Ax3man : Added linejoin parameter to geom_segment."
[15] "LSanselme : geom_density with groups of 1 or 2 elements"
[16] "philstraforelli : (feature request) Changing facet_wrap strip colour based on variable in data frame"
[17] "eliocamp : geom_tile() + coord_map() is extremely slow."
[18] "eliocamp : facet_wrap() doesn't play well with expressions in facets. "
[19] "dantonnoriega : Request: Quick visual example for each geom at http://ggplot2.tidyverse.org/reference/"
[20] "randomgambit : it would be nice to have date_breaks('0.2 sec')"
[21] "adrfantini : Labels can overlap in coord_sf()"
[22] "adrfantini : borders() is incompatible with coord_sf() with projected coordinates"
[23] "adrfantini : coord_proj() is superior to coord_map() and could be included in the default ggplot"
[24] "adrfantini : Coordinates labels and gridlines are wrong in coord_map()"
[25] "jonocarroll : Minor typo: monotonous -> monotonic"
[26] "FabianRoger : label.size in geom_label is ignored when printing to pdf"
[27] "andrewdolman : Add note recommending annotate"
[28] "Henrik-P : scale_identity doesn't play well with guide = \"legend\""
[29] "cpsievert : stat_sf(geom = \"text\")"
[30] "hadley : Automatically fill in x for univariate boxplot"
一個單一的公共API,顯示了紐約市自行車共享模擬的所有站點的位置、狀態和當前可用性。
citibike <- fromJSON("http://citibikenyc.com/stations/json")stations <- citibike$stationBeanListcolnames(stations)
[1] "id" "stationName"
[3] "availableDocks" "totalDocks"
[5] "latitude" "longitude"
[7] "statusValue" "statusKey"
[9] "availableBikes" "stAddress1"
[11] "stAddress2" "city"
[13] "postalCode" "location"
[15] "altitude" "testStation"
[17] "lastCommunicationTime" "landMark"
nrow(stations)
[1] 666
ergast
ergast開發人員API是一種實驗性的web服務,它為非商業目的提供了關於賽車資料的歷史記錄。res <- fromJSON('http://ergast.com/api/f1/2004/1/results.json')drivers <- res$MRData$RaceTable$Races$Results[[1]]$Drivercolnames(drivers)
[1] "driverId" "code" "url" "givenName"
[5] "familyName" "dateOfBirth" "nationality" "permanentNumber"
drivers[1:10, c("givenName", "familyName", "code", "nationality")]
givenName familyName code nationality
1 Michael Schumacher MSC German
2 Rubens Barrichello BAR Brazilian
3 Fernando Alonso ALO Spanish
4 Ralf Schumacher SCH German
5 Juan Pablo Montoya MON Colombian
6 Jenson Button BUT British
7 Jarno Trulli TRU Italian
8 David Coulthard COU British
9 Takuma Sato SAT Japanese
10 Giancarlo Fisichella FIS Italian
propublica
下面是propublica非營利的探索者API的一個例子,我們在那裡檢索了美國的第一個10頁的免稅組織,由收入訂購。rbind _pages函式用於將頁面組合成單個數據幀。#store all pages in a list firs
tbaseurl <- "https://projects.propublica.org/nonprofits/api/v1/search.json?order=revenue&sort_order=desc"
pages <- list()for(i in 0:10){
mydata <- fromJSON(paste0(baseurl, "&page=", i), flatten=TRUE)
message("Retrieving page ", i)
pages[[i+1]] <- mydata$filings}
#combine all into one
filings <- rbind_pages(pages)
#check outputnrow(filings)
[1] 275
filings[1:10, c("organization.sub_name", "organization.city", "totrevenue")]
organization.sub_name organization.city totrevenue
1 KAISER FOUNDATION HEALTH PLAN INC OAKLAND 40148558254
2 KAISER FOUNDATION HEALTH PLAN INC OAKLAND 37786011714
3 KAISER FOUNDATION HOSPITALS OAKLAND 20796549014
4 KAISER FOUNDATION HOSPITALS OAKLAND 17980030355
5 PARTNERS HEALTHCARE SYSTEM INC SOMERVILLE 10619215354
6 UPMC PITTSBURGH 10098163008
7 UAW RETIREE MEDICAL BENEFITS TR DETROIT 9890722789
8 THRIVENT FINANCIAL FOR LUTHERANS MINNEAPOLIS 9475129863
9 THRIVENT FINANCIAL FOR LUTHERANS MINNEAPOLIS 9021585970
10 DIGNITY HEALTH SAN FRANCISCO 8718896265
紐約時報
《紐約時報》作為紐約時報開發者網路的一部分,有幾個API。這些介面與來自不同部門的資料,如新聞文章、書評、房地產等。需要註冊(但免費),在這裡可以獲得一個金鑰。下面的程式碼包括一些用於說明目的的示例鍵。search for articles
article_key <- "&api-key=b75da00e12d54774a2d362adddcc9bef"
url <- "http://api.nytimes.com/svc/search/v2/articlesearch.json?q=obamacare+socialism"
req <- fromJSON(paste0(url, article_key))
articles <- req$response$docscolnames(articles)
[1] "web_url" "snippet" "lead_paragraph"
[4] "abstract" "print_page" "blog"
[7] "source" "multimedia" "headline"
[10] "keywords" "pub_date" "document_type"
[13] "news_desk" "section_name" "subsection_name"
[16] "byline" "type_of_material" "_id"
[19] "word_count" "slideshow_credits"
#search for best sellers
books_key <- "&api-key=76363c9e70bc401bac1e6ad88b13bd1d"
url <- "http://api.nytimes.com/svc/books/v2/lists/overview.json?published_date=2013-01-01"
req <- fromJSON(paste0(url, books_key))
bestsellers <- req$results$list
category1 <- bestsellers[[1, "books"]]
subset(category1, select = c("author", "title", "publisher"))
author title publisher
1 Gillian Flynn GONE GIRL Crown Publishing
2 John Grisham THE RACKETEER Knopf Doubleday Publishing
3 E L James FIFTY SHADES OF GREY Knopf Doubleday Publishing
4 Nicholas Sparks SAFE HAVEN Grand Central Publishing
5 David Baldacci THE FORGOTTEN Grand Central Publishing
#movie reviews
movie_key <- "&api-key=b75da00e12d54774a2d362adddcc9bef"
url <- "http://api.nytimes.com/svc/movies/v2/reviews/dvd-picks.json?order=by-date"
req <- fromJSON(paste0(url, movie_key))
reviews <- req$resultscolnames(reviews)
[1] "display_title" "mpaa_rating" "critics_pick"
[4] "byline" "headline" "summary_short"
[7] "publication_date" "opening_date" "date_updated"
[10] "link" "multimedia"
reviews[1:5, c("display_title", "byline", "mpaa_rating")]
display_title byline mpaa_rating
1 Hermia & Helena GLENN KENNY
2 The Women's Balcony NICOLE HERRINGTON
3 Long Strange Trip DANIEL M. GOLD R
4 Joshua: Teenager vs. Superpower KEN JAWOROWSKI
5 Berlin Syndrome GLENN KENNY R
陽光基金會
陽光基金會是一個非營利組織,有助於通過資料、工具、政策和新聞工作使政府透明和負責。在這裡註冊一個免費鑰匙。提供了一個示例金鑰。
key <- "&apikey=39c83d5a4acc42be993ee637e2e4ba3d"
key <- "&apikey=39c83d5a4acc42be993ee637e2e4ba3d"
#Find bills about drones
TwitterAPI需要oauth2身份驗證。一些示例程式碼:
#Create your own appication key at https://dev.twitter.com/apps consumer_key = "EZRy5JzOH2QQmVAe9B4j2w"; consumer_secret = "OIDC4MdfZJ82nbwpZfoUO4WOLTYjoRhpHRAWj6JMec"; #Use basic auth secret <- jsonlite::base64_enc(paste(consumer_key, consumer_secret, sep = ":")) req <- httr::POST("https://api.twitter.com/oauth2/token",httr::add_headers( "Authorization" = paste("Basic", gsub("\n", "", secret)), "Content-Type" = "application/x-www-form-urlencoded;charset=UTF-8"), body = "grant_type=client_credentials"); #Extract the access token httr::stop_for_status(req, "authenticate with twitter") token <- paste("Bearer", httr::content(req)$access_token) #Actual API call url <- "https://api.twitter.com/1.1/statuses/user_timeline.json?count=10&screen_name=Rbloggers" req <- httr::GET(url, httr::add_headers(Authorization = token)) json <- httr::content(req, as = "text") tweets <- fromJSON(json)substring(tweets$text, 1, 100) [1] "simmer 3.6.2 https://t.co/rRxgY2Ypfa #rstats #DataScience" [2] "Getting data for every Census tract in the US with purrr and tidycensus https://t.co/B3NYJS8sLO #rst" [3] "Gender Roles with Text Mining and N-grams https://t.co/Rwj0IaTiAR #rstats #DataScience" [4] "Data Science Podcasts https://t.co/SaAuO82a7M #rstats #DataScience" [5] "Reflections on ROpenSci Unconference 2017 https://t.co/87kMldvrsd #rstats #DataScience" [6] "Summarizing big data in R https://t.co/GMaZZ9sWiL #rstats #DataScience" [7] "Mining CRAN DESCRIPTION Files https://t.co/gWEIAYaBZF #rstats #DataScience" [8] "New package polypoly (helper functions for orthogonal polynomials) https://t.co/MzzzcIySym #rstats #" [9] "Hospital Infection Scores – R Shiny App https://t.co/Rf8wKNBPU6 #rstats #DataScience" [10] "New R job: Software Engineer in Test for RStudio https://t.co/X1bWkKlzYv #rstats #DataScience #jobs"