基于R实现多URL网页爬取:获取Justia法律条文终端URL问题
解决方案
1. 明确终端页面的判断规则
先分析Justia法律页面的结构:
- 非终端页面(需继续爬取):页面包含指向更细分章节/条文的链接,链接路径符合
/codes/[state]/[year]/title-xxx/.../格式; - 终端页面(需收集):页面仅展示具体法律条文文本,没有下一级条文链接,URL通常以
section-xxx结尾。
可通过两个维度判断:
- 页面存在特定的条文内容容器(比如CSS选择器
.statute-text,需根据实际页面调整); - 页面没有符合上述格式的下一级章节链接。
2. 实现递归爬取与去重
用递归函数替代多层循环,同时维护已爬取URL列表避免重复请求,核心逻辑:
- 传入待爬取URL,跳过已爬取的地址;
- 判断是否为终端页面:是则加入结果列表,否则提取有效内部链接并递归处理。
完整代码示例
library(rvest) library(purrr) # 初始化全局变量:存储终端URL和已爬取URL terminal_urls <- c() crawled_urls <- c() # 定义判断终端页面的函数 is_terminal_page <- function(page) { # 判断1:页面是否包含条文文本容器(根据实际页面结构调整CSS选择器) has_statute <- html_element(page, ".statute-text") %>% !is.na() # 判断2:页面是否没有下一级的章节链接 next_links <- html_elements(page, "a[href*='/codes/']") %>% html_attr("href") %>% str_subset("section-", negate = TRUE) %>% str_subset("^https://law.justia.com/codes/") has_next_links <- length(next_links) > 0 # 终端页面:有条文内容且无下一级链接 has_statute && !has_next_links } # 定义递归爬取函数 crawl_justia <- function(url) { if (url %in% crawled_urls) return() crawled_urls <<- c(crawled_urls, url) message("正在爬取: ", url) tryCatch({ page <- read_html(url) if (is_terminal_page(page)) { terminal_urls <<- c(terminal_urls, url) message("找到终端页面: ", url) return() } # 提取需继续爬取的内部链接 next_urls <- html_elements(page, "a[href*='/codes/']") %>% html_attr("href") %>% str_subset("^https://law.justia.com/codes/") %>% unique() %>% setdiff(crawled_urls) # 递归处理每个链接 walk(next_urls, crawl_justia) }, error = function(e) { message("爬取失败: ", url, " 错误信息: ", e$message) }) } # 启动爬取(测试用前9个州链接) start_urls <- read_html("https://law.justia.com/codes/") %>% html_elements("a[href*='/codes/']") %>% html_attr("href") %>% unique() %>% head(9) walk(start_urls, crawl_justia) # 查看并保存结果 print(terminal_urls) writeLines(terminal_urls, "justia_terminal_urls.txt")
3. 关键优化点
- 去重机制:通过
crawled_urls记录已爬取地址,避免重复请求和循环爬取; - 错误处理:用
tryCatch捕获请求失败情况,防止程序崩溃; - 链接过滤:通过正则和CSS选择器筛选目标链接,排除无关内容;
- 递归控制:自动处理多层嵌套页面,无需手动编写多层循环。
4. 注意事项
- 遵守网站
robots.txt规则,可添加Sys.sleep(1)控制请求频率,避免被封禁; - CSS选择器需根据实际页面结构调整,可通过浏览器开发者工具查看条文容器的类名。
内容的提问来源于stack exchange,提问作者Ophelia Hanson
相关产品推荐
相关产品推荐

