如何让R语言爬虫函数直接触发循环next,省略空值判断?
R语言爬虫函数优化:自动触发循环跳过
原函数与当前调用逻辑
你编写的get_page函数用于网页爬虫的错误处理,原代码如下:
get_page <- function(url, user_agent = "my information", skipped) { headers <- add_headers(`User-Agent` = user_agent) if (!exists(skipped, envir = .GlobalEnv)) { assign(skipped, c(), envir = .GlobalEnv) } for (attempt in 1:4) { response <- GET(url, headers = headers) http_code <- response$status_code if (http_code == 200) { page <- read_html(rawToChar(response$content)) return(page) } else if (http_code %in% c(400, 401, 403, 404)) { cat("HTTP", http_code, "error for", url, "\n") assign(skipped, c(get(skipped), url), envir = .GlobalEnv) return(NULL) } print(http_code) if (attempt == 4) { cat("Skipped", url, "\n") assign(skipped, c(get(skipped), url), envir = .GlobalEnv) return(NULL) } Sys.sleep(30) } }
当前调用时,必须手动判断返回值是否为NULL,再执行next跳过当前循环:
for (url in urls){ page <- get_page(url, skipped = "skipped_pers_aau") if (is.null(page)) { next } #...解析与存储代码 }
需求
希望修改后,调用get_page时无需手动写空值判断,函数能直接触发外层循环跳转到下一个URL,调用逻辑简化为:
for (url in urls){ page <- get_page(url, skipped = "skipped_pers_aau") #...解析与存储代码 }
可行解决方案
R语言中函数无法直接操控外层循环的next语句,但可以通过以下两种方式实现需求:
方法1:自定义错误+捕获处理
修改get_page,当需要跳过URL时不返回NULL,而是抛出带有自定义类的错误;然后在循环中用tryCatch捕获该错误,自动执行next。
修改后的get_page函数:
get_page <- function(url, user_agent = "my information", skipped) { headers <- add_headers(`User-Agent` = user_agent) if (!exists(skipped, envir = .GlobalEnv)) { assign(skipped, c(), envir = .GlobalEnv) } for (attempt in 1:4) { response <- GET(url, headers = headers) http_code <- response$status_code if (http_code == 200) { page <- read_html(rawToChar(response$content)) return(page) } else if (http_code %in% c(400, 401, 403, 404)) { msg <- paste("HTTP", http_code, "error for", url) cat(msg, "\n") assign(skipped, c(get(skipped), url), envir = .GlobalEnv) # 抛出自定义类的错误 stop(structure(list(message = msg, url = url), class = "skip_url_error")) } print(http_code) if (attempt == 4) { msg <- paste("Skipped", url) cat(msg, "\n") assign(skipped, c(get(skipped), url), envir = .GlobalEnv) # 抛出自定义类的错误 stop(structure(list(message = msg, url = url), class = "skip_url_error")) } Sys.sleep(30) } }
简化后的调用逻辑:
for (url in urls){ page <- tryCatch( get_page(url, skipped = "skipped_pers_aau"), # 捕获自定义错误,执行next跳过当前循环 skip_url_error = function(e) { next } ) #...解析与存储代码 }
方法2:封装循环逻辑
把URL循环、空值判断的逻辑封装到一个新函数中,外部只需调用这个封装函数,无需关注内部的跳过逻辑。
封装后的爬虫函数:
crawl_urls <- function(urls, user_agent = "my information", skipped_name = "skipped_pers_aau") { # 初始化skipped向量 if (!exists(skipped_name, envir = .GlobalEnv)) { assign(skipped_name, c(), envir = .GlobalEnv) } for (url in urls) { page <- get_page(url, user_agent, skipped_name) if (is.null(page)) next #...这里放置你的解析与存储代码 } }
外部调用时只需执行:
crawl_urls(urls)
两种方法各有优劣:方法1保留了外层循环的灵活性,适合需要在循环中添加额外逻辑的场景;方法2调用更简洁,适合标准化的爬虫流程。
内容的提问来源于stack exchange,提问作者EmilA
相关产品推荐
相关产品推荐

