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()#清除搜索框内容

}
相关推荐
CoderYanger10 小时前
动态规划算法-子序列问题(数组中不连续的一段):28.摆动序列
java·算法·leetcode·动态规划·1024程序员节
CoderYanger19 小时前
动态规划算法-子序列问题(数组中不连续的一段):30.最长数对链
java·算法·leetcode·动态规划·1024程序员节
CoderYanger20 小时前
C.滑动窗口——2762. 不间断子数组
java·开发语言·数据结构·算法·leetcode·1024程序员节
diegoXie1 天前
【R】正则的惰性和贪婪匹配
java·前端·r语言
综合热讯1 天前
远健生物宣布“重生因子 R-01”全球首创研发成功 细胞炎症逆转方向实现里程碑式突破
开发语言·人工智能·r语言
智者知已应修善业1 天前
【输入两个数字,判断两数相乘是否等于各自逆序数相乘】2023-10-24
c语言·c++·经验分享·笔记·算法·1024程序员节
CoderYanger2 天前
动态规划算法-子数组、子串系列(数组中连续的一段):21.乘积最大子数组
开发语言·算法·leetcode·职场和发展·动态规划·1024程序员节
CoderYanger2 天前
A.每日一题——3432. 统计元素和差值为偶数的分区方案
java·数据结构·算法·leetcode·1024程序员节
CoderYanger2 天前
动态规划算法-子数组、子串系列(数组中连续的一段):26.环绕字符串中唯一的子字符串
java·算法·leetcode·动态规划·1024程序员节
Jul1en_2 天前
【自动化测试】介绍Web自动化测试及Selenium安装
spring boot·功能测试·selenium