修正R爬虫代码:抓取KOSPI200纯股票投资信息并导出CSV
问题概述
需要抓取Naver财经中KOSPI200指数内排除ETN、ETF、REITs的纯股票的投资信息(对应页面红框内数据),原代码存在循环逻辑错误、变量初始化不当、缺少必要依赖包、未实现筛选规则及文件夹创建/网页保存步骤,导致无法运行。需修正代码并完成以下目标:
- 自动创建存储网页的文件夹(不存在时)
- 抓取符合条件的股票列表
- 读取并保存单只股票的网页文件
- 从保存的网页提取指定投资信息并生成DataFrame
- 将最终结果导出为CSV文件
原代码主要错误点
- 循环逻辑错误:
for (i in length(code_list))仅会执行一次循环,应遍历代码列表的所有索引 - 变量初始化错误:用数值0初始化存储URL和数据框的变量,无法容纳多个元素,需用列表
- 未导入
dplyr包:filter函数属于dplyr,原代码未加载 - 编码缺失:读取网页时未指定
encoding="euc-kr",可能导致乱码 - 缺少股票筛选逻辑:未筛选KOSPI200及排除ETN/ETF/REITs
- 未实现文件夹创建与网页保存功能
- 字符串分割逻辑缺陷:
str_split(" ")会误拆分含空格的数值,需更精准的正则匹配
修正后的完整代码
# 加载所需包 library(rvest) library(stringr) library(dplyr) # 1. 创建存储网页的文件夹(不存在时) save_dir <- "stock_webpages" if (!dir.exists(save_dir)) { dir.create(save_dir) } # 2. 获取KOSPI200中排除ETN/ETF/REITs的纯股票代码 kospi200_url <- "https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page=1" kospi200_html <- read_html(kospi200_url, encoding = "euc-kr") # 提取股票列表表格 stock_table <- kospi200_html %>% html_node("#contentarea_left > table.type_2") %>% html_table(fill = TRUE) # 筛选符合条件的股票:排除ETN、ETF、REITs,且属于KOSPI200 valid_stocks <- stock_table %>% filter(!str_detect(종목명, "ETN|ETF|REITs")) %>% pull(종목코드) # 3. 循环抓取单只股票网页并保存,同时提取投资信息 invest_info_list <- list() for (i in seq_along(valid_stocks)) { code <- valid_stocks[i] stock_url <- paste0("https://finance.naver.com/item/main.naver?code=", code) # 读取网页 webpage <- read_html(stock_url, encoding = "euc-kr") # 保存网页到文件夹 save_path <- file.path(save_dir, paste0(code, ".html")) write_html(webpage, save_path) # 提取投资信息所在的tab ID invest_tab_id <- webpage %>% html_nodes("a[href*=tab_invest]") %>% html_attr("onclick") %>% str_extract("(?<=showArea\\('tab_invest',')[^']+(?='\\))") # 提取投资信息表格数据 invest_data <- webpage %>% html_node(paste0("#", invest_tab_id)) %>% html_nodes(".aside_invest_table > tbody > tr") %>% html_text() %>% str_remove_all("[\r\n\t]") %>% str_trim() %>% # 用正则拆分:按第一个空格拆分,处理值含空格的情况 str_split("(?<=^[^\\s]+)\\s", n = 2) %>% # 转换为数据框 do.call(rbind, .) %>% as.data.frame(stringsAsFactors = FALSE) %>% setNames(c("항목", "값")) %>% # 筛选需要的字段 filter(항목 %in% c("시가총액", "시가총액순위", "상장주식수", "액면가", "매매단위", "외국인한도주식수", "외국인한도주식수(A)", "외국인보유주식수(B)", "외국인소진율(B/A)", "투자의견", "목표주가", "52주최고", "52주최저", "PER", "EPS", "추정PER", "추정EPS", "PBR", "BPS", "배당수익률", "동일업종PER", "동일업종등락률")) # 添加股票代码和名称 stock_name <- webpage %>% html_node("#middle > div.h_company > div.wrap_company > h2 > a") %>% html_text() invest_data <- invest_data %>% mutate(종목코드 = code, 종목명 = stock_name) %>% relocate(종목코드, 종목명, .before = 항목) # 存入列表 invest_info_list[[i]] <- invest_data } # 4. 合并所有数据并导出为CSV final_invest_data <- bind_rows(invest_info_list) write.csv(final_invest_data, "Korean_investment_info.csv", row.names = FALSE, fileEncoding = "euc-kr")
代码说明
- 文件夹创建:自动检查并创建
stock_webpages文件夹,用于保存抓取的网页文件 - 股票筛选:从KOSPI200列表中排除含ETN/ETF/REITs关键词的品种,确保只抓取纯股票
- 网页保存:每只股票的网页以
[股票代码].html格式保存到指定文件夹,方便后续复用 - 数据提取优化:用正则
str_split("(?<=^[^\\s]+)\\s", n = 2)拆分项目和值,避免误拆分含空格的数值(如"52주최고 10,000원") - 数据整合:每只股票的信息添加代码和名称后,合并为统一DataFrame,最后导出为CSV(指定编码避免乱码)
内容的提问来源于stack exchange,提问作者R starter
相关产品推荐
相关产品推荐

