如何为R语言迭代式网页爬虫脚本添加请求头解决403错误
R爬虫爬Trustpilot遇403错误:正确添加请求头及批量爬取方案
问题核心
爬取Trustpilot多页评论时,因无请求头的批量请求被网站反爬机制拦截,触发HTTP error 403;尝试两种添加请求头的方式均报错,需明确批量爬取场景下请求头的正确添加位置及方式。
之前尝试的错误分析
预先GET请求传入爬虫函数的错误
你把GET()返回的响应对象直接传给爬虫函数,但函数大概率期望接收URL字符串,导致后续字符串拼接时出现类型不匹配,触发stri_c的类型强制转换警告。GET()返回的是response对象,并非纯URL字符串,不能直接当作参数传入处理页面内容的函数。生成URL列表时嵌入GET请求的错误
语法逻辑完全错误:str_c是用来拼接字符串的工具,不能将GET请求嵌入其中生成URL列表;同时GET()的参数格式也不符合语法要求,正确的流程是先生成纯URL字符串列表,再对每个URL发起请求。
正确解决方案
1. 封装带合法请求头的页面获取函数
先写一个通用函数,确保每次请求都携带模拟浏览器的请求头,同时处理响应状态:
library(httr) library(rvest) library(dplyr) library(purrr) # 封装带请求头的页面获取函数 get_trustpilot_page <- function(page_url) { # 构造模拟浏览器的请求头,可根据需求调整User-Agent request_headers <- add_headers( `User-Agent` = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", `Accept` = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", `Referer` = "https://www.trustpilot.com/" ) # 发送请求并设置超时 response <- GET(page_url, request_headers, timeout(10)) # 检查响应状态,失败则返回空并抛出警告 if (status_code(response) != 200) { warning(paste("请求失败:URL=", page_url, "状态码=", status_code(response))) return(NULL) } # 返回解析后的HTML文档 return(read_html(response)) }
2. 批量生成纯URL字符串列表
先生成所有需要爬取的页面URL,这里不要执行请求操作:
# 目标品牌基础URL base_url <- "https://www.trustpilot.com/review/www.travelocity.com" # 生成1到417页的URL列表 page_urls <- paste0(base_url, "?page=", 1:417)
3. 遍历URL批量爬取,添加反爬延迟
遍历每个URL时调用请求函数,同时添加随机延迟避免请求频率过高,再解析评论数据:
# 单页评论解析函数(需根据页面实际HTML结构调整选择器) scrape_single_page <- function(html_doc, brand_name) { if (is.null(html_doc)) return(tibble()) html_doc %>% html_elements(".review-card") %>% map_dfr(function(card) { tibble( brand = brand_name, review_title = card %>% html_element(".review-content__title") %>% html_text2(), review_content = card %>% html_element(".review-content__text") %>% html_text2(), star_rating = card %>% html_element(".star-rating") %>% html_attr("data-rating") %>% as.integer(), review_date = card %>% html_element(".review-content-header__dates") %>% html_text2() ) }) } # 批量爬取所有页面 all_reviews <- map_dfr(page_urls, function(url) { # 随机延迟1-3秒,降低请求频率 Sys.sleep(runif(1, 1, 3)) page_html <- get_trustpilot_page(url) scrape_single_page(page_html, "travelocity") })
4. 额外反爬优化建议
- 请求头多样化:如果爬取量极大,可准备多个
User-Agent,每次请求随机挑选一个。 - 403重试机制:在
get_trustpilot_page函数中添加重试逻辑,比如遇到403时等待5-10秒后重试2-3次。 - 遵守robots规则:提前查看Trustpilot的
robots.txt,确认是否允许爬取评论页面,避免违反网站协议。
小范围爬取正常的原因
小批量请求(1-50页)的频率未触发网站反爬阈值,而417页的请求量超过了Travelocity对应的阈值(不同域名的反爬阈值可能不同,Expedia的288页刚好在阈值内),因此触发403拦截。
内容的提问来源于stack exchange,提问作者supercarp
相关产品推荐
相关产品推荐

