抓取动态网页(接下来如何模拟在浏览器页面中滑动鼠标获得多屏搜索结果)

优采云 发布时间: 2022-02-07 08:13

  抓取动态网页(接下来如何模拟在浏览器页面中滑动鼠标获得多屏搜索结果)

  让我们现在开始谈正事。第一步是在docker中连接Selenium服务器:

  1library(RSelenium)    # 激活包remDr "localhost" , port = 4445L , browserName = "chrome")                     # 设置连接参数remDr$open()          # 开始连接

2

  第二步,打开百度搜索首页,输入搜索关键词,点击搜索:

  1remDr$navigate("https://www.baidu.com") # 打开remDr$screenshot(display = TRUE) # 截屏看一下首页xpath '//*[@id="kw"]' # 根据上面定位在界面中找到文字输入框webElem "xpath", value = xpath)   # 在搜索框里输入搜索关键词‘R Cran’,然后点击回车键webElem$sendKeysToElement(list("R Cran", key = "enter")) # # 再次截屏显示搜索结果remDr$screenshot(display = TRUE)

2

  这是我的两张截图的结果:

  

  

  我们知道百度默认一屏显示10个搜索结果。在接下来的第三步中,我们将第一屏的 10 个结果删减:

  1# 调用静态网页抓取常用包rvestlibrary(rvest)# 获取网页背后的html源代码webpage # 利用节点ID挑出10项搜索结果的内容标题result_html # 下面两行利用xpath挑出10项搜索结果的内容标题# xpath # result_html # 挑出html代码中10个标题内容result_name head(result_name,10)# 找出10个标题对应的超级链接result_link # 存成数据框result_df = data.frame(result_name=result_name, result_link=result_link)

2

  10个搜索结果出来了,如果我们想模拟一个浏览器点击一个搜索结果怎么办?例如,第一个结果“综合 R 档案网络”。让我们开始吧:

  1# 直接在搜索结果界面中定位10项搜索结果标题webElems 'css selector', # 把结果标题变成文本单独拎出来resHeaders function(x){x$getElementText()}))resHeaders# 准备点击第一个搜索结果webElem "The Comprehensive R Archive Network")]]# 模拟浏览器点击第一个结果超级链接,并在新窗口中打开webElem$clickElement()webElem$sendKeysToElement(list(key = "control", "w"))# 此时浏览器有两个窗口,下面几行进行窗口切换(窗口ID会动态变化)remDr$getWindowHandles()remDr$getCurrentWindowHandle()remDr$switchToWindow("CDwindow-2BA4D55F9BABCA20D3DFE2FECBA3D85A")remDr$getCurrentWindowHandle()# 获取新窗口的网址和标题,并截屏remDr$getCurrentUrl()remDr$getTitle()remDr$screenshot(display = TRUE)

2

  第一个链接打开后的截图结果如下:

  以上是使用RSelenium动态爬取百度搜索结果。接下来,我想展示如何在浏览器页面中模拟滑动鼠标,以获得多屏显示的所有内容。毕竟滑动鼠标后才能看到所有的网页内容,然后再抓取内容。这里以河北省的一家三级医院为例。

  第一步是打开链接:

  1remDr$navigate("https://m.yyk.99.com.cn/sanjia/hebei/")remDr$screenshot(display = TRUE)

2

  

  如果不出意外,这次我们能够从 20 家医院获取信息。

  1# 获取网页背后的html源代码webpage $getPageSource()[[# 找出医院名字对应的节点名称hospital_name_html 'h2')# 将医院名字从html转换为文本hospital_name # 调用stringr包把医院名字前的空格等多余符号去掉library(stringr)hospital_name "\r\n",# 看看前10家医院的名字head(hospital_name,10)# 看看总共有多少家医院length(hospital_name)    # 结果为20

2

  其实,在鼠标滑动几次之后,我们发现这个页面一共收录了75家医院的信息。第一次抓取只能拿到前20个,因为医院信息需要先滑动鼠标。

  接下来,我们在R中运行Java代码,实现鼠标在当前网页上滑动的效果。此外,我们不想一次又一次地滑动,而是一次滑动到页面底部。

  1# window.scrollTo是Java的函数,括号里跟着x和y的屏幕位置数字。比如第一个0表示屏幕最左端;# document.body.scrollHeight表示屏幕上鼠标一次滑动的最大高度,即当面页面的最底部。# 那么,下面的代码显示我们要重复地滑到页面的最底端,每次滑动中间停顿3秒,好让网页内容得以显示。# 最后,滑到不能再滑动的时候,我们就停住了。比如,第一个0表示屏幕最左端,last_height = 0 #repeat { remDr$executeScript("window.scrollTo(0,document.body.scrollHeight);") Sys.sleep(3) #delay by 3sec to give chance to load. # Updated if statement which breaks if we can't scroll further new_height = remDr$executeScript("return document.body.scrollHeight") if(unlist(last_height) == unlist(new_height)) { break } else { last_height = new_height }}

2

  这样显示完这个网页的所有内容后,我们就可以按照静态网页爬取75家医院的所有数据了:

  1webpage $getPageSource()[[hospital_name_html 'h2')hospital_name library(stringr)hospital_name "\r\n",head(hospital_name,10)length(hospital_name)    # 结果为75

2

  到目前为止,我们已经解决了动态网页抓取的两个主要问题:一是抓取搜索引擎生成的搜索结果界面的相关内容;另一种是爬取多屏显示的动态网页的相关内容。当然,这两个问题几乎没有涵盖许多其他动态网页抓取的案例。比如后者还包括点击动态网页中的方向箭头(显示其他隐藏的内容)、从同一个网页的不同栏目(框架界面)抓取不同的内容等等。

  在我的探索过程中,我也发现虽然可以爬取百度搜索结果,但谷歌结果却很难实现。一位知*敏*感*词*士告诉我,虽然你电脑上的浏览器可以用VPN打开google,但Selenium没有VPN可以打开google,这是真的。所以,我找到了很多关于如何通过谷歌搜索使用RSelenium抓取谷歌搜索结果的方法,我想复制它,但发现同样的方法对我不起作用。

  就是这样。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线