R语言爬虫实战:如何爬取分页链接并批量保存

1. 引言

在数据采集和分析过程中,爬虫技术(Web Scraping)是一项非常重要的技能。R语言虽然以统计分析和数据可视化闻名,但其强大的网络爬虫能力同样不容忽视。本文将介绍如何使用R语言爬取分页网页的链接,并将数据批量保存到本地文件(如CSV或TXT),适用于新闻聚合、电商数据抓取、学术研究等场景。

2. 准备工作

在开始之前,确保已安装以下R包:

  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">rvest</font>**:用于HTML解析和数据提取
  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">httr</font>**:用于HTTP请求(处理GET/POST请求)
  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">dplyr</font>**:用于数据清洗和整理
  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">stringr</font>**:用于字符串处理

3. 目标分析

假设我们要爬取一个新闻网站(如示例网站 **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://example-news.com</font>**),该网站的分页结构如下:

  • 首页:**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://example-news.com/page/1</font>**
  • 第二页:**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://example-news.com/page/2</font>**
  • ...
  • 第N页:**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://example-news.com/page/N</font>**

我们的任务是:

  1. 爬取所有分页的新闻标题和链接
  2. 存储到本地CSV文件

4. 实现步骤

4.1 获取单页链接

首先,我们编写一个函数 **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">scrape_page()</font>**,用于抓取单页的新闻标题和链接:

plain 复制代码
library(rvest)
library(httr)
library(dplyr)
library(stringr)

scrape_page <- function(page_url) {
  # 发送HTTP请求
  response <- GET(page_url, user_agent("Mozilla/5.0"))
  if (status_code(response) != 200) {
    stop("Failed to fetch the page")
  }
  
  # 解析HTML
  html_content <- read_html(response)
  
  # 提取新闻标题和链接(假设标题在<h2>标签,链接在<a>标签)
  titles <- html_content %>%
    html_nodes("h2 a") %>%
    html_text(trim = TRUE)
  
  links <- html_content %>%
    html_nodes("h2 a") %>%
    html_attr("href")
  
  # 返回数据框
  data.frame(Title = titles, URL = links, stringsAsFactors = FALSE)
}

4.2 爬取多页数据

由于网站是分页的,我们需要循环爬取多个页面。这里以爬取前5页为例:

plain 复制代码
base_url <- "https://example-news.com/page/"
max_pages <- 5

all_news <- data.frame()

for (page in 1:max_pages) {
  page_url <- paste0(base_url, page)
  cat("Scraping:", page_url, "\n")
  
  tryCatch({
    page_data <- scrape_page(page_url)
    all_news <- bind_rows(all_news, page_data)
  }, error = function(e) {
    cat("Error scraping page", page, ":", e$message, "\n")
  })
  
  # 避免被封IP,设置延迟
  Sys.sleep(2)
}

# 查看爬取的数据
head(all_news)

4.3 数据去重

由于某些网站可能在不同分页出现相同新闻,我们需要去重

plain 复制代码
all_news <- all_news %>%
  distinct(URL, .keep_all = TRUE)

4.4 保存到CSV文件

最后,将数据保存到本地:

plain 复制代码
write.csv(all_news, "news_links.csv", row.names = FALSE)
cat("Data saved to 'news_links.csv'")

5. 完整代码

plain 复制代码
library(rvest)
library(httr)
library(dplyr)
library(stringr)

# 代理配置
proxyHost <- "www.16yun.cn"
proxyPort <- "5445"
proxyUser <- "16QMSOML"
proxyPass <- "280651"

# 单页爬取函数(已添加代理)
scrape_page <- function(page_url) {
  # 设置代理
  proxy_config <- use_proxy(
    url = proxyHost,
    port = as.integer(proxyPort),
    username = proxyUser,
    password = proxyPass
  )
  
  # 发送HTTP请求(带代理)
  response <- GET(
    page_url, 
    user_agent("Mozilla/5.0"),
    proxy_config
  )
  
  if (status_code(response) != 200) {
    stop(paste("Failed to fetch the page. Status code:", status_code(response)))
  }
  
  # 解析HTML
  html_content <- read_html(response)
  
  # 提取新闻标题和链接(假设标题在<h2>标签,链接在<a>标签)
  titles <- html_content %>%
    html_nodes("h2 a") %>%
    html_text(trim = TRUE)
  
  links <- html_content %>%
    html_nodes("h2 a") %>%
    html_attr("href")
  
  # 返回数据框
  data.frame(Title = titles, URL = links, stringsAsFactors = FALSE)
}

# 爬取多页数据
base_url <- "https://example-news.com/page/"
max_pages <- 5

all_news <- data.frame()

for (page in 1:max_pages) {
  page_url <- paste0(base_url, page)
  cat("Scraping:", page_url, "\n")
  
  tryCatch({
    page_data <- scrape_page(page_url)
    all_news <- bind_rows(all_news, page_data)
  }, error = function(e) {
    cat("Error scraping page", page, ":", e$message, "\n")
  })
  
  # 随机延迟1-3秒,避免被封
  Sys.sleep(sample(1:3, 1))
}

# 数据去重
all_news <- all_news %>%
  distinct(URL, .keep_all = TRUE)

# 保存到CSV文件
write.csv(all_news, "news_links.csv", row.names = FALSE)
cat("Data saved to 'news_links.csv'")

7. 总结

本文介绍了如何使用R语言爬取分页网站数据,并保存到本地CSV文件。关键步骤包括:

  1. 单页数据抓取 (**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">rvest</font>** + **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">httr</font>**)
  2. 循环爬取多页 (**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">for</font>**/**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">while</font>** 循环)
  3. 数据清洗与存储 (**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">dplyr</font>** + **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">write.csv</font>**)
  4. 进阶优化(并行爬取、反爬虫策略)
相关推荐
dialect_5 小时前
KMP算法
开发语言·c++·算法
总要学点什么6 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
开开心心_Every8 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
chenbingjie_c8 小时前
C++ 多态完全指南:从虚函数重写到虚函数表原理
开发语言·c++
吴卫斌8 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
超级架构师9 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
叼烟扛炮10 小时前
Linux 学习笔记(四十三):网络编程进阶——自定义协议解决 TCP 粘包与守护进程
linux·开发语言·网络·笔记·tcp/ip
LMT流氓兔10 小时前
第五单元——第十六课:给书店助手加上网页界面
java·开发语言·jvm·人工智能·oracle·langchain·1024程序员节
专注仿真10 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
外收内放11 小时前
Python基础语法练习题(75)
开发语言·python·学习