R语言基于selenium模拟浏览器抓取ASCO数据-连载NO.03

A:当前获取数据的网站是ASCO,xpath代码是对应网站内的搜索框、搜索按钮、翻页等功能,都经过反复验证,可以正确获取需要的数据

B:当前数据获取没有经过海量数据验证,目前经过实际获取的3个关键词数据量在1w左右,所以如果需要百万级等以上的数据还需要更多的避免抓取异常和抓取性能的优化

C:selenium版本不宜过高,会导致java调用不兼容,无法正常启动java服务或者正常拉起浏览器(大概是这个意思),已经尝试过更高版本的selenium

1、目标网站和内容准备

R 复制代码
#添加需要搜索的内容
search_content <- c("content1","content2","content3")
#需要获取数据的网址
spider_url_base <- "https://meetings.asco.org/abstracts-presentations/search?query=*&q=*&sortBy=Relevancy&pageNumber=1&filters=%7B%22meetingTypeName%22:%5B%7B%22key%22:%22ASCO%20Annual%20Meeting%22%7D%5D,%22meetingYear%22:%5B%7B%22key%22:%222025%22%7D%5D%7D&size=20"

2、隐藏selenium特征(简单设置,表头、IP池策略等等都没有做,用处不大,未经过大量验证)

R 复制代码
# 隐藏Selenium特征的JavaScript代码
hide_automation_script <- "
Object.defineProperty(navigator, 'webdriver', {
  get: () => undefined
});
window.chrome = {
  runtime: {},
  // etc.
};
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
  parameters.name === 'notifications' ?
    Promise.resolve({ state: Notification.permission }) :
    originalQuery(parameters)
);
"

3、启动java服务和浏览器

R 复制代码
#每次获取xpath位置后点击、发送内容等操作最好间隔点时间,否则极大可能造成操作无效
#启动selenium服务
system("java -jar \"你的selenium文件路径/selenium-server-standalone-3.141.59.jar \" -port 4445",wait = FALSE,invisible = FALSE)

remdr <- remoteDriver(browserName ="firefox",
                      version='0.36.0',
                      port=4445)
#如果port被占用,cmd中查看端口占用netstat -ano
#打开浏览器
remdr$open()

4、跳转至目标网站并处理网站弹窗

R 复制代码
Sys.sleep(runif(1, 2, 5))#暂停下再导航到对应网页
# 导航到目标网页
#跳转到目标网站,注意网站打开的时间消耗
remdr$navigate(spider_url_base )
#这里是为了确认网站的cookies弹窗
url_cookies_accept <- remdr$findElement("xpath", "//button[@id='onetrust-accept-btn-handler'][text()='Accept All']")
Sys.sleep(runif(1, 2, 5))#暂停下再导航到对应网页
url_cookies_accept$clickElement()

# 在每次请求前执行JavaScript
remdr$executeScript(script = hide_automation_script)

5、数据抓取与保存

R 复制代码
#准备好存储数据的表
asco_data_cancer_all <- data.frame()
asco_data_cancer_each<- data.frame()
asco_data_cancer_pageeach<- data.frame()

#搜索了3个关键词,所以最外层循环是3次
for (i in 1:3) {
  # 定位搜索框并输入内容
  search_box <- remdr$findElement(using = "xpath", value = "//*[@id='smallSearchbar']") # 替换为实际的搜索框XPath
  search_box$sendKeysToElement(list(search_content[i])) # 替换为实际的搜索查询
  Sys.sleep(runif(1, 3, 6))#暂停下再点击
  # 定位搜索按钮并点击
  search_button <- remdr$findElement(using = "xpath", value = "//mat-icon[@class='mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted' and @aria-hidden='true']") # 替换为实际的搜索按钮XPath
  Sys.sleep(runif(1, 5, 10))#暂停下再点击
  search_button$clickElement()


  # 获取完整HTML内容,这里是为了获取页数
  page_html_source <- remdr$getPageSource()[[1]]

  cat(sprintf("Progress: %s",str_c( search_content[i],"的文章信息已开始提取,当前时间:",Sys.time())),sep='\n')

    Sys.sleep(runif(1, 5, 9))
    asco_data_cancer_each <- data.frame()
    loop_times=0#初始循环次数,为了知道数据获取的情况
    repeat{
      # 获取完整HTML内容
      page_html_source <- remdr$getPageSource()[[1]]
      page_html_content <- rvest::read_html(page_html_source)
      #获取文章名称
      article_name=page_html_content %>%
        html_nodes(xpath = "//input[contains(@class,'mat-checkbox-input') and contains(@class,'cdk-visually-hidden')]/@aria-label") %>%
        html_text()
      #获取文章类型
      article_type=page_html_content   %>%
        #这个xpath值定位也可以://div/span[@class="ng-star-inserted" and not(span/@class)]
        html_nodes(xpath = "//div[@class='eyebrow'][text()='Abstracts & Presentations']/following-sibling::div//span") %>% 
        html_text()
      #获取文章链接
      article_link=page_html_content   %>%
        html_nodes(xpath = "//asco-link[@class='pseudo-hover']//a[@href]") %>% 
        html_attr('href')
      #每一页数据合并
asco_data_cancer_pageeach=data.frame(article_name[-1],article_type,article_link,cancer_type=search_content[i])
      #当前关键词所有页数据合并
      asco_data_cancer_each=bind_rows(asco_data_cancer_each,asco_data_cancer_pageeach)
      #数据获取进度
      proc.time() - ptm
      current_page_url=remdr$getCurrentUrl()[[1]]#获取当前页面的网址
      Sys.sleep(runif(1, 10, 15))
      #下一页点击
      nextpage_button <- remdr$findElement(using = "xpath", value = "//mat-icon[contains(., 'arrow_right')]") # 
      
      Sys.sleep(runif(1, 6, 10))
      nextpage_button$clickElement()#如果间隔很短点击可能翻页不能及时生效
      Sys.sleep(runif(1, 1, 3))
      nextpage_button$clickElement()#如果间隔很短点击可能翻页不能及时生效
      Sys.sleep(runif(1, 5, 10))
      next_page_url=remdr$getCurrentUrl()[[1]]#获取下一页面的网址
      loop_times=loop_times+1

      cat("翻页前后2个页面是否相同",current_page_url,"第",loop_times,"个",current_page_url==next_page_url,sep="\n")
      if(current_page_url==next_page_url){
        cat("已到达最后一页,URL未变化",
            "当前页:",current_page_url,"下一页:",next_page_url,sep='\n')
        break
      }
    }
  #所有关键词数据合并
  asco_data_cancer_all=bind_rows(asco_data_cancer_all,asco_data_cancer_each)
  Sys.sleep(runif(1, 5, 10))
  #清空搜索框内容
  search_box <- remdr$findElement(using = "xpath", value = "//*[@id='smallSearchbar']") # 替换为实际的搜索框XPath
  Sys.sleep(runif(1, 3, 6))
  search_box$clearElement()#清除搜索框内容

}
相关推荐
GeminiJM4 小时前
在Windows上使用Selenium + Chrome Profile实现自动登录爬虫
1024程序员节
PyAIGCMaster5 小时前
设置一个自定义名称的密钥,用于 git 仓库上下传使用
1024程序员节
物联网软硬件开发-轨物科技5 小时前
【轨物方案】母线槽智能在线监测解决方案:构筑电力系统安全防线,驱动制造业数智化升级
1024程序员节
潜心编码5 小时前
基于Django的医疗电子仪器系统
前端·数据库·1024程序员节
Dontla5 小时前
Web单页应用(SPA)路由设计(以React为例)
1024程序员节
colus_SEU5 小时前
【计算机网络笔记】第二章 应用层 (Application Layer)
笔记·计算机网络·1024程序员节
上海蓝色星球5 小时前
蓝色星球如何打造能与企业共同进化的灵活系统
1024程序员节
yychen_java6 小时前
无人机技术研究现状及发展趋势
无人机·1024程序员节
小白黑科技测评6 小时前
2025 年视频去水印工具实测:擦擦视频双版本解析一键去字幕与多格式兼容能力
java·人工智能·音视频·智能电视·1024程序员节