```{r setup_15, echo=FALSE, message=FALSE}
library(tidyverse)
library(rvest)
```


# Learning goals {.unnumbered .smaller}

After this lesson, you should be able to:

- Use CSS Selectors and the Selector Gadget tool to locate data of interest within a webpage
- Use the `html_elements()`, `html_text()`, and  `html_attr()` functions within the `rvest` packages to scrape data from webpage using CSS selectors.

<br>



<br><br><br><br>

            
# Web scraping {.unnumbered .smaller}

## When to Use {.unnumbered .smaller}

We have talked about how to acquire data from APIs. Whenever an API is available for your project, you should default to getting data from the API. 

Sometimes an API will not be available, and **web scraping** is another means of getting data.

Web scraping describes the use of code to extract information displayed on a web page. 

In R, the `rvest` package offers tools for scraping. (`rvest` is meant to sound like "harvest".)

Additional readings:  

- [rvest](https://cran.r-project.org/web/packages/rvest/vignettes/rvest.html)
- [CSS selectors](https://css-tricks.com/how-css-selectors-work/)

## Ethics {.unnumbered .smaller}

`robots.txt` is a file that some websites will publish to clarify what can and cannot be scraped and other constraints about scraping. 

When a website publishes this file, this we need to comply with the information in it for moral and legal reasons.

. . .

We will look through the information in [this tutorial](https://www.zenrows.com/blog/robots-txt-web-scraping) and apply this to the [NIH robots.txt file](https://www.nih.gov/robots.txt).

. . .

From our investigation of the NIH `robots.txt`, we learn:

:::{.incremental}

- `User-agent: *`: Anyone is allowed to scrape
- `Crawl-delay: 2`: Need to wait 2 seconds between each page scraped
- No `Visit-time` entry: no restrictions on time of day that scraping is allowed
- No `Request-rate` entry: no restrictions on simultaneous requests
- No mention of `?page=`, `news-events`, `news-releases`, or `https://science.education.nih.gov/` in the `Disallow` sections. (This is what we want to scrape today.)
:::

. . .

**Further considerations**

The article [Ethics in Web Scraping](https://towardsdatascience.com/ethics-in-web-scraping-b96b18136f01) describes some good principles to ensure that we are valuing the labor that website owners invested to provide data and creating good from the information we do scrape.


## HTML structure {.unnumbered .smaller}

HTML (hypertext markup language) is the formatting language used to create webpages. 

Let's look at the core parts of HTML from the [rvest vignette](https://cran.r-project.org/web/packages/rvest/vignettes/rvest.html).

. . .

Key HTML Concepts:

- **Elements** which consist of a start tag (e.g. `<tag>`) and end with an end tag (e.g. `</tag>`) 
- Optional **attributes** (`id='first'`) within the start tag
- **Contents** of an element 

. . .

Key CSS Concepts:

- To identify part of the html code, we can use the tag type (e.g. `<a>`, `<h1>`, `<p>`) and class or id attributes.
- Each element can have a **class** attribute and/or an **id** attribute.
- We can also identify parts of the code based on whether they are children or descendants of other elements, in that they are contained within an element. We won't need this for simple applications.


## Finding CSS Selectors {.unnumbered .smaller}

In order to gather information from a webpage, we must learn the language used to identify patterns of specific information. 

For example, on the [NIH News Releases page](https://www.nih.gov/news-events/news-releases), we can see that the data is represented in a consistent pattern of image + title + abstract.

. . .

We will identify data in a web page using a pattern matching language called [CSS Selectors](https://css-tricks.com/how-css-selectors-work/) that can refer to specific patterns in HTML, the language used to write web pages.

. . .

For example:

:::{.incremental}
- Selecting by element/tag type:
    - `"a"` selects all hyperlinks in a webpage ("a" represents "anchor" links in HTML)
    - `"p"` selects all paragraph elements
- Selecting by ID and class:
    - `".description"` selects all elements with `class` equal to "description"
        - The `.` at the beginning is what signifies `class` selection.
        - This is one of the most common CSS selectors for scraping because in HTML, the `class` attribute is extremely commonly used to format webpage elements. (Any number of HTML elements can have the same `class`, which is not true for the `id` attribute.)
    - `"#mainTitle"` selects the SINGLE element with **id** equal to "mainTitle"
        - The `#` at the beginning is what signifies `id` selection.
:::

. . .

```html
<p class="title">Title of resource 1</p>
<p class="description">Description of resource 1</p>

<p class="title">Title of resource 2</p>
<p class="description">Description of resource 2</p>
```

. . .

**Warning**: Websites change often! So if you are going to scrape a lot of data, it is probably worthwhile to save and date a copy of the website (File > Save As). Otherwise, you may return after some time and your scraping code will include all of the wrong CSS selectors.

. . .

Although you can [learn how to use CSS Selectors by hand]([CSS Selectors](https://css-tricks.com/how-css-selectors-work/)), we will use a shortcut by installing the [Selector Gadget](http://selectorgadget.com/) tool.

- There is a version available for Chrome--add it to Chrome via the [Chome Web Store](https://chromewebstore.google.com/detail/selectorgadget/mhjhnkcfbdhnjickkkdbjoemdmbfginb).
    - Make sure to pin the extension to the menu bar. (Click the 3 dots > Extensions > Manage extensions. Click the "Details" button under SelectorGadget and toggle the "Pin to toolbar" option.)
- There is also a version that can be saved as a bookmark in the browser--see [here](https://rvest.tidyverse.org/articles/selectorgadget.html).

Let's watch the Selector Gadget [tutorial video](http://selectorgadget.com/) before proceeding.

## Example 1: NIH New Releases {.unnumbered .smaller}

Head over to the [NIH News Releases page](https://www.nih.gov/news-events/news-releases). 

Click the Selector Gadget extension icon or bookmark button. 

As you mouse over the webpage, different parts will be highlighted in orange. 

Click on the title of the first news release. 

You'll notice that the Selector Gadget information in the lower right describes what you clicked on.

Scroll through the page to verify that only the information you intend (the description paragraph) is selected. 

- The selector panel shows the CSS selector (`.teaser-title`) and the number of matches for that CSS selector (10). (You may have to be careful with your clicking--there are two overlapping boxes, and clicking on the link of the title can lead to the CSS selector of "a".)

**Exercise:** Repeat the process above to find the correct selectors for the following fields. Make sure that each matches 10 results:

- The publication date
- The article abstract paragraph (which will also include the publication date)





## Retrieving Data Using `rvest` and CSS Selectors {.unnumbered .smaller}

Now that we have identified CSS selectors for the information we need, let's fetch the data using the `rvest` package.

```{r read_html}
nih <- read_html("https://www.nih.gov/news-events/news-releases")
```

Once the webpage is loaded, we can retrieve data using the CSS selectors we specified earlier. The following code retrieves the article titles:

```{r html_elements_text}
# Retrieve and inspect article titles
article_titles <- nih %>%
    html_elements(".teaser-title") %>%
    html_text()
head(article_titles)
```

**Exercise:** Our goal is to get article titles, publication dates, and abstract text for news releases across several pages of results. 

**Before doing any coding,** plan your approach. 

- What functions will you write? 
- What arguments will they have? 
- How will you use your functions? 

Consult with your peers and compare plans.

::: {.callout-tip title="Stop to reflect"}
Write a few observations about your comfort/confidence in this planning exercise. As you proceed through the implementation of this plan in the next steps, make notes about any places you struggled, were uncertain, or benefited from peer input.
:::

**Exercise:** Carry out your plan to get the article title, publication date, and abstract text for the first 5 pages of news releases in a single data frame. You will need to write at least one function, and you will need iteration--Start with an appropriate `map()` function from `purrr`. If you have time, also try to use a `for` loop instead.

Notes:

- Mouse over the page buttons at the very bottom of the news home page to see what the URLs look like.
- The abstract should not have the publication date--use `stringr` and regular expressions to remove the publication date.
- Include `Sys.sleep(2)` in your function to respect the `Crawl-delay: 2` in the NIH `robots.txt` file.
- Recall that `bind_rows()` from `dplyr` and `list_rbind()` from `purrr` takes a list of data frames and stacks them on top of each other.




<br><br><br><br>


## Example 2: NIH STEM Teaching Resources {.unnumbered .smaller}

Let's look at a more complex example with the [NIH STEM Teaching Resources webpage](https://science.education.nih.gov/).

-  Using Selector Gadget to select the resource titles can be tricky if we can only get one resource title at a time.
- In Chrome, you can right click part of a web page and click "Inspect". This opens up Chrome's Developer Tools. Mousing over the HTML in the top right panel highlights the corresponding part of the web page.
    - For non-Chrome browsers, use the Help menu to search for Developer Tools.

The underlying HTML used to create a web page is also called the page **source code** or **page source**. 

We learn from this that the resource titles are `<h4>` headings that have the class `resource-title`. 

We can infer from this that `.resource-title` would be the CSS selector for the resource titles.
## Done!

- Render your notes.
- Check the solutions in the course website (Solution drop downs).
- If you finish all that during class, start your homework!


