Home
Softono
h

hrbrmstr

Professional software vendor delivering innovative solutions on the Softono platform. Specialized in both open-source and proprietary software development.

Total Products
2

Software by hrbrmstr

splashr
Open Source

splashr

[![Travis-CI Build Status](https://travis-ci.org/hrbrmstr/splashr.svg?branch=master)](https://travis-ci.org/hrbrmstr/splashr) [![Coverage Status](https://img.shields.io/codecov/c/github/hrbrmstr/splashr/master.svg)](https://codecov.io/github/hrbrmstr/splashr?branch=master) [![CRAN\_Status\_Badge](http://www.r-pkg.org/badges/version/splashr)](https://cran.r-project.org/package=splashr) [![](http://cranlogs.r-pkg.org/badges/splashr)](http://cran.rstudio.com/web/packages/splashr/index.html) # `splashr` : Tools to Work with the ‘Splash’ JavaScript Rendering Service TL;DR: This package works with Splash rendering servers which are really just a REST API & `lua` scripting interface to a QT browser. It’s an alternative to the Selenium ecosystem which was really engineered for application testing & validation. Sometimes, all you need is a page scrape after javascript has been allowed to roam wild and free over meticulously crafted HTML tags. So, this package does not do *everything* Selenium can in pure R (though, the Lua interface is equally as powerful and accessible via R), but if you’re just trying to get a page back that needs javascript rendering, this is a nice, lightweight, consistent alternative. It’s also an alternative to the somewhat abandoned `phantomjs` (which you can use in R within or without a Selenium context as it’s it’s own webdriver) and it may be useful to compare renderings between this package & `phantomjs`. The package uses the [`stevedore`](https://github.com/richfitz/stevedore) package to orchestrate Docker on your system (if you have Docker and more on how to use the `stevedore` integration below) but you can also do get it running in Docker on the command-line with two commands: sudo docker pull scrapinghub/splash:latest --disable-browser-caches sudo docker run -p 5023:5023 -p 8050:8050 -p 8051:8051 scrapinghub/splash:latest --disable-browser-caches Do whatever you Windows ppl do with Docker on your systems to make ^^ work. Folks super-new to Docker on Unix-ish platforms should [make sure to do](https://github.com/hrbrmstr/splashr/issues/3#issuecomment-280686494): sudo groupadd docker sudo usermod -aG docker $USER (`$USER` is your username and shld be defined for you in the environment) If using the [`stevedore`](https://github.com/richfitz/stevedore) package you can use the convience wrappers in this pacakge: install_splash() splash_container <- start_splash() and then run: stop_splash(splash_container) when done. All of that happens on your `localhost` and you will not need to specify `splash_obj` to many of the `splashr` functions if you’re running Splash in this default configuration as long as you use named parameters. You can also use the pre-defined `splash_local` object if you want to use positional parameters. Now, you can run Selenium in Docker, so this is not unique to Splash. But, a Docker context makes it so that you don’t have to run or maintain icky Python stuff directly on your system. Leave it in the abandoned warehouse district where it belongs. All you need for this package to work is a running Splash instance. You provide the host/port for it and it’s scrape-tastic fun from there\! ### About Splash > ‘Splash’ <https://github.com/scrapinghub/splash> is a javascript > rendering service. It’s a lightweight web browser with an ‘HTTP’ API, > implemented in Python using ‘Twisted’and ’QT’ \[and provides some of > the core functionality of the ‘RSelenium’ or ‘seleniumPipes’ R > packages but with a Java-free footprint\]. The (twisted) ‘QT’ reactor > is used to make the sever fully asynchronous allowing to take > advantage of ‘webkit’ concurrency via QT main loop. Some of Splash > features include the ability to process multiple webpages in parallel; > retrieving HTML results and/or take screenshots; disabling images or > use Adblock Plus rules to make rendering faster; executing custom > JavaScript in page context; getting detailed rendering info in HAR > format. The following functions are implemented: - `render_html`: Return the HTML of the javascript-rendered page. - `render_har`: Return information about Splash interaction with a website in [HAR](http://www.softwareishard.com/blog/har-12-spec/) format. - `render_jpeg`: Return a image (in JPEG format) of the javascript-rendered page. - `render_png`: Return a image (in PNG format) of the javascript-rendered page. - `execute_lua`: Execute a custom rendering script and return a result. - `splash`: Configure parameters for connecting to a Splash server - `install_splash`: Retrieve the Docker image for Splash - `start_splash`: Start a Splash server Docker container - `stop_splash`: Stop a running a Splash server Docker container Mini-DSL (domain-specific language). These can be used to create a “script” without actually scripting in Lua. They are a less-powerful/configurable set of calls than what you can make with a full Lua function but the idea is to have it take care of very common but simple use-cases, like waiting a period of time before capturing a HAR/HTML/PNG image of a site: - `splash_plugins`: Enable or disable browser plugins (e.g. Flash). - `splash_click`: Trigger mouse click event in web page. - `splash_focus`: Focus on a document element provided by a CSS selector - `splash_images`: Enable/disable images - `splash_response_body`: Enable or disable response content tracking. - `splash_go`: Go to an URL. - `splash_wait`: Wait for a period time - `splash_har`: Return information about Splash interaction with a website in HAR format. - `splash_html`: Return a HTML snapshot of a current page. - `splash_png`: Return a screenshot of a current page in PNG format. - `splash_press`: Trigger mouse press event in web page. - `splash_release`: Trigger mouse release event in web page. - `splash_send_keys`: Send keyboard events to page context. - `splash_send_text`: Send text as input to page context, literally, character by character. - `splash_user_agent`: Overwrite the User-Agent header for all further requests. NOTE: There are many “helper” user agent strings to go with `splash_user_agent`. Look for objects in `splashr` starting with `ua_`. `httr` helpers. These help turn various bits of `splashr` objects into `httr`-ish things: - `as_req`: Turn a HAR response entry into a working `httr` function you can use to make a request with - `as_request`: Turn a HAR response entry into an `httr` `response`-like object (i.e. you can use `httr::content()` on it) Helpers: - `tidy_har`: Turn a gnHARly HAR object into a tidy data frame - `get_body_size`: Retrieve size of content | body | headers - `get_content_sie`: Retrieve size of content | body | headers - `get_content_type` Retrieve or test content type of a HAR request object - `get_headers_size` Retrieve size of content | body | headers - `is_binary`: Retrieve or test content type of a HAR request object - `is_content_type`: Retrieve or test content type of a HAR request object - `is_css`: Retrieve or test content type of a HAR request object - `is_gif`: Retrieve or test content type of a HAR request object - `is_html`: Retrieve or test content type of a HAR request object - `is_javascript`: Retrieve or test content type of a HAR request object - `is_jpeg`: Retrieve or test content type of a HAR request object - `is_json`: Retrieve or test content type of a HAR request object - `is_plain`: Retrieve or test content type of a HAR request object - `is_png`: Retrieve or test content type of a HAR request object - `is_svg`: Retrieve or test content type of a HAR request object - `is_xhr`: Retrieve or test content type of a HAR request object - `is_xml`: Retrieve or test content type of a HAR request object Some functions from `HARtools` are imported/exported and `%>%` is imported/exported. ### TODO Suggest more in a feature req\! - <strike>Implement `render.json`</strike> - <strike>Implement “file rendering”</strike> - <strike>Implement `execute` (you can script Splash\!)</strike> - <strike>Add integration with [`HARtools`](https://github.com/johndharrison/HARtools)</strike> - <strike>*Possibly* writing R function wrappers to install/start/stop Splash</strike> which would also support enabling javascript profiles, request filters and proxy profiles from with R directly, using [`harbor`](https://github.com/wch/harbor) - Re-implement `render_file()` - Testing results with all combinations of parameters ### Installation ``` r # CRAN install.packages("splashr") # DEV # See DESCRIPTION for non-CINC-provided dependencies install.packages("splashr", repos = c("https://cinc.rud.is/")) ``` ### Usage NOTE: ALL of these examples assume Splash is running in the default configuraiton on `localhost` (i.e. started with `start_splash()` or the docker example commands) unless otherwise noted. ``` r library(splashr) library(magick) library(rvest) library(anytime) library(tidyverse) # current verison packageVersion("splashr") ``` ## [1] '0.7.0' ``` r splash_active() ``` ## [1] TRUE ``` r splash_debug() ``` ## List of 7 ## $ active : list() ## $ argcache: int 0 ## $ fds : int 59 ## $ leaks :List of 5 ## ..$ Deferred : int 20 ## ..$ DelayedCall: int 3 ## ..$ LuaRuntime : int 1 ## ..$ QTimer : int 1 ## ..$ Request : int 1 ## $ maxrss : int 219096 ## $ qsize : int 0 ## $ url : chr "http://localhost:8050" ## - attr(*, "class")= chr [1:2] "splash_debug" "list" ## NULL Notice the difference between a rendered HTML scrape and a non-rendered one: ``` r render_html(url = "http://marvel.com/universe/Captain_America_(Steve_Rogers)") ``` ## {html_document} ## <html lang="en"> ## [1] <head class="at-element-marker">\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n<meta char ... ## [2] <body class="terrigen">\n<div id="__next"><div id="terrigen-page" class="page"><div id="page-wrapper" class="page ... ``` r xml2::read_html("http://marvel.com/universe/Captain_America_(Steve_Rogers)") ``` ## {html_document} ## <html lang="en"> ## [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n<meta charset="utf-8" class="next-he ... ## [2] <body class="terrigen">\n<div id="__next"><div id="terrigen-page" class="page"><div id="page-wrapper" class="page ... You can also profile pages: ``` r render_har(url = "http://www.poynter.org/") -> har print(har) ``` ## --------HAR VERSION-------- ## HAR specification version: 1.2 ## --------HAR CREATOR-------- ## Created by: Splash ## version: 3.4.1 ## --------HAR BROWSER-------- ## Browser: QWebKit ## version: 602.1 ## --------HAR PAGES-------- ## Page id: 1 , Page title: Poynter - Poynter ## --------HAR ENTRIES-------- ## Number of entries: 270 ## REQUESTS: ## Page: 1 ## Number of entries: 270 ## - http://www.poynter.org/ ## - https://www.poynter.org/ ## - https://www.googletagservices.com/tag/js/gpt.js ## - https://www.poynter.org/wp-includes/js/wp-emoji-release.min.js?ver=5.3.2 ## - https://www.poynter.org/wp-includes/css/dist/block-library/style.min.css?ver=5.3.2 ## ........ ## - https://www.poynter.org/wp-content/themes/elumine-child/assets/fonts/PoynterOSDisplay/PoynterOSDisplay-BoldItalic... ## - https://securepubads.g.doubleclick.net/gampad/ads?gdfp_req=1&pvsid=3405643238502098&correlator=142496486392385&ou... ## - https://securepubads.g.doubleclick.net/gpt/pubads_impl_rendering_2020021101.js ## - https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html ## - https://static.chartbeat.com/js/chartbeat.js ``` r tidy_har(har) ``` ## # A tibble: 270 x 20 ## status started total_time page_ref timings req_url req_method req_http_version req_hdr_size req_headers req_cookies ## <int> <chr> <int> <chr> <I<lis> <chr> <chr> <chr> <int> <I<list>> <I<list>> ## 1 301 2020-0… 171 1 <tibbl… http:/… GET HTTP/1.1 189 <tibble [2… <tibble [0… ## 2 200 2020-0… 238 1 <tibbl… https:… GET HTTP/1.1 189 <tibble [2… <tibble [0… ## 3 200 2020-0… 135 1 <tibbl… https:… GET HTTP/1.1 164 <tibble [3… <tibble [0… ## 4 200 2020-0… 93 1 <tibbl… https:… GET HTTP/1.1 164 <tibble [3… <tibble [0… ## 5 200 2020-0… 158 1 <tibbl… https:… GET HTTP/1.1 179 <tibble [3… <tibble [0… ## 6 200 2020-0… 218 1 <tibbl… https:… GET HTTP/1.1 179 <tibble [3… <tibble [0… ## 7 200 2020-0… 262 1 <tibbl… https:… GET HTTP/1.1 179 <tibble [3… <tibble [0… ## 8 200 2020-0… 265 1 <tibbl… https:… GET HTTP/1.1 179 <tibble [3… <tibble [0… ## 9 200 2020-0… 266 1 <tibbl… https:… GET HTTP/1.1 179 <tibble [3… <tibble [0… ## 10 200 2020-0… 269 1 <tibbl… https:… GET HTTP/1.1 179 <tibble [3… <tibble [0… ## # … with 260 more rows, and 9 more variables: resp_url <chr>, resp_rdrurl <chr>, resp_type <chr>, resp_size <int>, ## # resp_cookies <I<list>>, resp_headers <I<list>>, resp_encoding <chr>, resp_content_size <dbl>, resp_content <chr> You can use [`HARtools::HARviewer`](https://github.com/johndharrison/HARtools/blob/master/R/HARviewer.R) — which this pkg import/exports — to get view the HAR in an interactive HTML widget. Full web page snapshots are easy-peasy too: ``` r render_png(url = "http://www.marveldirectory.com/individuals/c/captainamerica.htm") ``` ![](img/cap.png) ``` r render_jpeg(url = "http://static2.comicvine.com/uploads/scale_small/3/31666/5052983-capasr2016001-eptingvar-18bdb.jpg") ``` ![](img/cap.jpg) ### Executing custom Lua scripts ``` r lua_ex <- ' function main(splash) splash:go("http://rud.is/b") splash:wait(0.5) local title = splash:evaljs("document.title") return {title=title} end ' splash_local %>% execute_lua(lua_ex) -> res rawToChar(res) %>% jsonlite::fromJSON() ``` ## $title ## [1] "rud.is | \"In God we trust. All others must bring data\"" ### Interacting With Flash sites ``` r splash_local %>% splash_plugins(TRUE) %>% splash_go("https://gis.cdc.gov/GRASP/Fluview/FluHospRates.html") %>% splash_wait(4) %>% splash_click(460, 550) %>% splash_wait(2) %>% splash_click(230, 85) %>% splash_wait(2) %>% splash_png() ``` <img src="img/flash.png" width="50%"/> ``` r stop_splash(splash_vm) ``` ### Code of Conduct Please note that this project is released with a [Contributor Code of Conduct](CONDUCT.md). By participating in this project you agree to abide by its terms.

Browser Automation
96 Github Stars
htmlunit
Open Source

htmlunit

[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![Signed by](https://img.shields.io/badge/Keybase-Verified-brightgreen.svg)](https://keybase.io/hrbrmstr) ![Signed commit %](https://img.shields.io/badge/Signed_Commits-100%25-lightgrey.svg) [![Linux build Status](https://travis-ci.org/hrbrmstr/htmlunit.svg?branch=master)](https://travis-ci.org/hrbrmstr/htmlunit) [![Coverage Status](https://codecov.io/gh/hrbrmstr/htmlunit/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/htmlunit) ![Minimal R Version](https://img.shields.io/badge/R%3E%3D-3.6.0-blue.svg) ![License](https://img.shields.io/badge/License-Apache-blue.svg) # htmlunit Tools to Scrape Dynamic Web Content via the ‘HtmlUnit’ Java Library ## Description ‘HtmlUnit’ (<https://htmlunit.sourceforge.net/>) is a “‘GUI’-Less browser for ‘Java’ programs”. It models ‘HTML’ documents and provides an ‘API’ that allows one to invoke pages, fill out forms, click links and more just like one does in a “normal” browser. The library has fairly good and constantly improving ‘JavaScript’ support and is able to work even with quite complex ‘AJAX’ libraries, simulating ‘Chrome’, ‘Firefox’ or ‘Internet Explorer’ depending on the configuration used. It is typically used for testing purposes or to retrieve information from web sites. Tools are provided to work with this library at a higher level than provided by the exposed ‘Java’ libraries in the ‘htmlunitjars’ package. ## What’s Inside The Tin The following functions are implemented: ### DSL - `web_client`/`webclient`: Create a new HtmlUnit WebClient instance<br/><br/> - `wc_go`: Visit a URL<br/> - `wc_html_nodes`: Select nodes from web client active page html content - `wc_html_text`: Extract attributes, text and tag name from webclient page html content<br/><br/> - `wc_html_attr`: Extract attributes, text and tag name from webclient page html content - `wc_html_name`: Extract attributes, text and tag name from webclient page html content - `wc_headers`: Return response headers of the last web request for current page - `wc_browser_info`: Retreive information about the browser used to create the ‘webclient’ - `wc_content_length`: Return content length of the last web request for current page - `wc_content_type`: Return content type of web request for current page<br/><br/> - `wc_render`: Retrieve current page contents<br/><br/> - `wc_css`: Enable/Disable CSS support - `wc_dnt`: Enable/Disable Do-Not-Track - `wc_geo`: Enable/Disable Geolocation - `wc_img_dl`: Enable/Disable Image Downloading - `wc_load_time`: Return load time of the last web request for current page - `wc_resize`: Resize the virtual browser window - `wc_status`: Return status code of web request for current page - `wc_timeout`: Change default request timeout - `wc_title`: Return page title for current page - `wc_url`: Return load time of the last web request for current page - `wc_use_insecure_ssl`: Enable/Disable Ignoring SSL Validation Issues - `wc_wait`: Block HtlUnit final rendering blocks until all background JavaScript tasks have finished executing ### Just the Content (pls) - `hu_read_html`: Read HTML from a URL with Browser Emulation & in a JavaScript Context ### Content++ - `wc_inspect`: Perform a “Developer Tools”-like Network Inspection of a URL ## Installation ``` r install.packages("htmlunit", repos = c("https://cinc.rud.is", "https://cloud.r-project.org/")) # or remotes::install_git("https://git.rud.is/hrbrmstr/htmlunit.git") # or remotes::install_git("https://git.sr.ht/~hrbrmstr/htmlunit") # or remotes::install_gitlab("hrbrmstr/htmlunit") # or remotes::install_bitbucket("hrbrmstr/htmlunit") # or remotes::install_github("hrbrmstr/htmlunit") ``` NOTE: To use the ‘remotes’ install options you will need to have the [{remotes} package](https://github.com/r-lib/remotes) installed. ## Usage ``` r library(htmlunit) library(tidyverse) # for some data ops; not req'd for pkg # current verison packageVersion("htmlunit") ## [1] '0.5.0' ``` Something `xml2::read_html()` cannot do, read the table from <https://hrbrmstr.github.io/htmlunitjars/index.html>: ![](man/figures/test-url-table.png) ``` r test_url <- "https://hrbrmstr.github.io/htmlunitjars/index.html" pg <- xml2::read_html(test_url) html_table(pg) ## list() ``` ☹️ But, `hu_read_html()` can\! ``` r pg <- hu_read_html(test_url) html_table(pg) ## [[1]] ## X1 X2 ## 1 One Two ## 2 Three Four ## 3 Five Six ``` All without needing a separate Selenium or Splash server instance. ### Content++ We can also get a HAR-like content + metadata dump: ``` r xdf <- wc_inspect("https://rstudio.com") colnames(xdf) ## [1] "method" "url" "status_code" "message" "content" "content_length" ## [7] "content_type" "load_time" "headers" select(xdf, method, url, status_code, content_length, load_time) ## # A tibble: 36 x 5 ## method url status_code content_length load_time ## <chr> <chr> <int> <dbl> <dbl> ## 1 GET https://rstudio.com/ 200 14621 495 ## 2 GET https://metadata-static-files.sfo2.cdn.digitaloceanspaces.com/pixel/lp.js 200 3576 221 ## 3 GET https://snap.licdn.com/li.lms-analytics/insight.min.js 200 1576 162 ## 4 GET https://connect.facebook.net/en_US/fbevents.js 200 34269 138 ## 5 GET https://connect.facebook.net/signals/config/151855192184380?v=2.9.23&r=s… 200 134841 66 ## 6 GET https://munchkin.marketo.net/munchkin-beta.js 200 752 230 ## 7 GET https://munchkin.marketo.net/159/munchkin.js 200 4810 27 ## 8 GET https://x.clearbitjs.com/v1/pk_60c5aa2221e3c03eca10fb6876aa6df7/clearbit… 200 86568 483 ## 9 GET https://cdn.segment.com/analytics.js/v1/gO0uTGfCkO4DQpfkRim9mBsjdKrehtnu… 200 62860 243 ## 10 GET https://static.hotjar.com/c/hotjar-1446157.js?sv=6 200 1708 212 ## # … with 26 more rows group_by(xdf, content_type) %>% summarise( total_size = sum(content_length), total_load_time = sum(load_time)/1000 ) ## # A tibble: 7 x 3 ## content_type total_size total_load_time ## <chr> <dbl> <dbl> ## 1 application/javascript 431338 2.58 ## 2 application/json 4118 1.37 ## 3 application/x-javascript 176248 0.623 ## 4 image/gif 35 0.232 ## 5 text/html 16640 1.36 ## 6 text/javascript 254971 0.996 ## 7 text/plain 28 0.189 ``` ### DSL ``` r wc <- web_client(emulate = "chrome") wc %>% wc_browser_info() ## < Netscape / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 / en-US > wc <- web_client() wc %>% wc_go("https://usa.gov/") # if you want to use purrr::map_ functions the result of wc_html_nodes() needs to be passed to as.list() wc %>% wc_html_nodes("a") %>% sapply(wc_html_text, trim = TRUE) %>% head(10) ## [1] "Skip to main content" "" "Español" ## [4] "1-844-USA-GOV1" "All Topics and Services" "About the U.S." ## [7] "American Flag" "Branches of the U.S. Government" "Budget of the U.S. Government" ## [10] "Data and Statistics about the U.S." wc %>% wc_html_nodes(xpath=".//a") %>% sapply(wc_html_text, trim = TRUE) %>% head(10) ## [1] "Skip to main content" "" "Español" ## [4] "1-844-USA-GOV1" "All Topics and Services" "About the U.S." ## [7] "American Flag" "Branches of the U.S. Government" "Budget of the U.S. Government" ## [10] "Data and Statistics about the U.S." wc %>% wc_html_nodes(xpath=".//a") %>% sapply(wc_html_attr, "href") %>% head(10) ## [1] "#content" "/" "/espanol/" "/phone" ## [5] "/#tpcs" "#" "/flag" "/branches-of-government" ## [9] "/budget" "/statistics" ``` Handy function to get rendered plain text for text mining: ``` r wc %>% wc_render("text") %>% substr(1, 300) %>% cat() ## Official Guide to Government Information and Services | USAGov ## Skip to main content ## An official website of the United States government Here's how you know ## ## ## Main Navigation ## Search ## Search ## Search ## 1-844-USA-GOV1 ## All Topics and Services ## Benefits, Grants, Loans ## Government Agencies and Elected Officials ``` ### htmlunit Metrics | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | | :---- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | | R | 14 | 0.70 | 341 | 0.72 | 188 | 0.70 | 377 | 0.82 | | Java | 3 | 0.15 | 52 | 0.11 | 23 | 0.09 | 3 | 0.01 | | Rmd | 1 | 0.05 | 41 | 0.09 | 52 | 0.19 | 75 | 0.16 | | Maven | 1 | 0.05 | 30 | 0.06 | 0 | 0.00 | 1 | 0.00 | | make | 1 | 0.05 | 10 | 0.02 | 4 | 0.01 | 4 | 0.01 | clock Package Metrics for htmlunit ## Code of Conduct Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

JavaScript Libraries & Components Browser Automation
36 Github Stars