Remove href and/or deactivate anchored links when printing a PDF from HTML using xml2 and pagedown with R

Viewed 193

I'm using R to extract 100s of articles from a food blog and convert them to PDF. I'm 99% done, but when I print the final PDF, in-line hyperlinks have their URL written right within the text. I do not want every link rendered to text in the PDF, and believe I need to remove the href attributes from the HTML prior to printing with pagedown. Does anyone know how to do this? My example code below should get you to my pdf creation loop for the first article. The initial portions pull all of the URLs into a vector. The portion that needs this enhancementThanks.

library(rvest)
library(dplyr)
library(tidyr)
library(stringr)
library(purrr)
library(downloader)
library(pagedown)
library(xml2)
library(htmltools)

#Specifying the url for desired website to be scraped

url1 <- paste0('https://www.foodrepublic.com/author/george-embiricos/page/', '1', '/')

#Reading the HTML code from the website
webpage1 <- read_html(url1)

# Pull the links for all articles on George's initial author page

dat <- html_attr(html_nodes(webpage1, 'a'), "href") %>%
  as_tibble() %>%
  filter(str_detect(value, "([0-9]{4})")) %>%
  unique() %>%
  rename(link=value)

dat <- head(dat, 10)

# Pull the links for all articles on George's 2nd-89th author page

for (i in 2:89) {

url <- paste0('https://www.foodrepublic.com/author/george-embiricos/page/', i, '/')

#Reading the HTML code from the website
webpage <- read_html(url)

links <- html_attr(html_nodes(webpage, 'a'), "href") %>%
  as_tibble() %>%
  filter(str_detect(value, "([0-9]{4})")) %>%
  unique() %>%
  rename(link=value)

dat <- bind_rows(dat, links) %>%
  unique()

}

dat <- dat %>%
  arrange(link)

dat <- tail(dat, 890)

articleUrls <- dat$link[1]

# Mac

# Windows
setwd("YOUR-WD")

# articleUrls <- articleUrls[1]

for(i in seq_along(articleUrls)) {
  
  filename <- str_extract(articleUrls[i], "[^/]+(?=/$|$)")
 
  a <- read_html(articleUrls[i]) 
  xml_remove(a %>% xml_find_all("aside"))
  xml_remove(a %>% xml_find_all("footer"))
  xml_remove(a %>% xml_find_all(xpath = "//*[contains(@class, 'article-related mb20')]"))
  xml_remove(a %>% xml_find_all(xpath = "//*[contains(@class, 'tags')]"))
  #xml_remove(a %>% xml_find_all("head") %>% xml2::xml_find_all("script"))
  xml_remove(a %>% xml2::xml_find_all("//script"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'ad box')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'newsletter-signup')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'article-footer')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'article-footer-sidebar')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'site-footer')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'sticky-newsletter')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'site-header')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, '.fb_iframe_widget')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, '_8f1i')]"))
  xml_remove(a %>% xml_find_all("//*[contains(@class, 'newsletter-toggle')]"))      
  
  # xml_remove(a %>% xml_find_all("//*[contains(@class, 'articleBody')]"))
  
  # xml_remove(a %>% xml_find_all("//href='([^\"]*)'"))

  xml2::write_html(a, file = paste0("html/", filename, ".html"))
  
  tryCatch(pagedown::chrome_print(input = paste0("html/", filename, ".html"),
                         output=paste0("pdf/", filename, ".pdf"),
                         format="pdf", timeout = 300, verbose=0,
                         wait=20), error=function(e) paste("wrong"))
  
}

You can see a screenshot of what I'm seeing below. The "< >" portion containing the URL should not display. It should only say "King's Brew".

You can see a screenshot of what I'm seeing below. The "< >" portion containing the URL should not display. It should only say "King's Brew".

1 Answers

Try something like this:

library(dplyr)
library(xml2)

allHref <- a %>% xml_find_all("//a")
for (l in allHref) {
  cntnt <- l %>% xml_text(trim = T)
  xml_replace(l, read_xml(paste0("<span>", cntnt, "</span>")))    
}

First of all we find all links. Then, for each one of them we extract its content and replace the link itself with this content.

Related