美文网首页数据分析商业智能BI那点事儿我爱编程
左手用R右手Python系列——动态网页抓取与selenium驱

左手用R右手Python系列——动态网页抓取与selenium驱

作者: 天善智能 | 来源:发表于2017-12-23 13:57 被阅读110次

感谢关注天善智能,走好数据之路↑↑↑

欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

本文作者:天善智能社区专家杜雨

天善智能社区地址:https://www.hellobi.com/


本节以下内容正式分享今日案例,目标是拉勾网(不要问为什么,因为之前我还没有爬过拉钩)!

在介绍案例之前,请确保系统具备以下条件:

本地有selenium服务器并添加系统路径;

本地有plantomjs浏览器并添加系统路径;

安装了RSelenium包。

因为涉及到自动化点击操作,Chrome浏览器倒腾一下午硬是在点击环节出故障,找到了原因,因为拉勾网页面很长,而下一页按钮不在默认视窗范围内,使用了js脚本控制滑动条失败,原因不明,看到有人用firefox浏览器测试成功,我还没有试过,这里改用plantomjs无头浏览器(无需考虑元素是否被窗口遮挡的问题。)

R语言版:

#!!!这两句是在cmd后者PowerShell中运行的!

#RSelenium服务未关闭之前,请务必保持该窗口状态!

###启动selenium服务:

cd D:\

java -jar selenium-server-standalone-3.3.1.jar

##selenium服务器也可以直接在R语言中启动(无弹出窗口)

system("java -jar \"D:/selenium-server-standalone-2.53.1.jar\"",wait = FALSE,invisible = FALSE)

#加载包

library("RSelenium")

library("magrittr")

library("xml2")

启动服务

#给plantomjs浏览器伪装UserAgent

eCap<- list(phantomjs.page.settings.userAgent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0")

###伪装浏览器UserAgent,为什么即使使用plantomjs这种浏览器也需要伪装UA呢,

###因为plantomjs是专门用于web端页面测试的,通常都是在自己的web项目中测试web端功能,直接拿去抓别人的网站,默认的UA就是plantomjs;

###这是公然的挑衅!

###连接plantomjs服务

remDr<- remoteDriver(browserName="phantomjs", extraCapabilities= eCap)

构建自动化抓取函数:

#自动化抓取函数:

myresult<-function(remDr,url){

###初始化一个数据框,用作后期收据收集之用!

myresult<-data.frame()

###调用后台浏览器(因为是plantomjs这种无头浏览器(headless),所以你看不到弹出窗口)

remDr$open()

###打开导航页面(也就是直达要抓取的目标网址)

remDr$navigate(url)

###初始化一个计时器(用于输出并查看任务进度)

i =0

while(TRUE){

#计时器开始计数:

i = i+1

#范回当前页面DOM

pagecontent<-remDr$getPageSource()[[1]]

#以下三个字段共用一部分祖先节点,所以临时建立了一个根节点(节省冗余代码)

con_list_item       <- pagecontent %>%read_html() %>% xml_find_all('//ul[@class="item_con_list"]/li')

#职位名称

position.name       <- con_list_item %>% xml_attr("data-positionname")

#公司名称

position.company    <- con_list_item %>% xml_attr("data-company")

#职位薪资

position.salary     <- con_list_item %>% xml_attr("data-salary")

#职位详情链接

position.link       <- pagecontent %>%read_html() %>% xml_find_all('//div[@class="p_top"]/a') %>% xml_attr("href")

#职位经验要求

position.exprience  <- pagecontent %>%read_html() %>% xml_find_all('//div[@class="p_bot"]/div[@class="li_b_l"]') %>% xml_text(trim=TRUE)

#职位所述行业

position.industry   <- pagecontent %>%read_html() %>% xml_find_all('//div[@class="industry"]') %>% xml_text(trim=TRUE) %>% gsub("[[:space:]\\u00a0]+|\\n","",.)

#职位福利

position.bonus      <- pagecontent %>%read_html() %>% xml_find_all('//div[@class="list_item_bot"]/div[@class="li_b_l"]') %>% xml_text(trim=TRUE) %>% gsub("[[:space:]\\u00a0]+|\\n","/",.)

#职位工作环境

position.environment<- pagecontent %>%read_html() %>% xml_find_all('//div[@class="li_b_r"]') %>% xml_text(trim=TRUE)

#收集数据

mydata<- data.frame(position.name,position.company,position.salary,position.link,position.exprience,position.industry,position.bonus,position.environment,stringsAsFactors = FALSE)

#将本次收集的数据写入之前创建的数据框

myresult<-rbind(myresult,mydata)

#系统休眠0.5~1.5秒

Sys.sleep(runif(1,0.5,1.5))

#判断页面是否到尾部

if( pagecontent %>%read_html() %>% xml_find_all('//div[@class="page-number"]/span[1]') %>% xml_text() !="30"){

#如果页面未到尾部,则点击下一页

remDr$findElement('xpath','//div[@class="pager_container"]/a[last()]')$clickElement()

#但因当前任务进度

cat(sprintf("第【%d】页抓取成功",i),sep ="\n")

}else{

#如果页面到尾部则跳出while循环

break

}

}

#跳出循环后关闭remDr服务窗口

remDr$close()

#但因全局任务状态(也即任务结束)

cat("all work is done!!!",sep ="\n")

#返回最终数据

return(myresult)

}

运行抓取函数

url <-"https://www.lagou.com/zhaopin"

myresult <- myresult(remDr,url)

#预览

DT::datatable(myresult)

Python:

importos,random,time

importpandasaspd

fromseleniumimportwebdriver

fromselenium.webdriver.common.desired_capabilities

importDesiredCapabilities

fromlxmlimportetree

启动服务

dcap = dict(DesiredCapabilities.PHANTOMJS)

#这里也是伪装一下UA:

dcap["phantomjs.page.settings.userAgent"] = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0")

#启动服务(python里面的selenium内置有selenium服务器,需要本地启动)

driver = webdriver.PhantomJS(desired_capabilities=dcap)

构建抓取函数

defgetlaogou(driver,url):

#初始化一个长度为0的空字典!以备之后收集数据

myresult = {

"position_name":[],

"position_company":[],

"position_salary":[],

"position_link":[],

"position_exprience":[],

"position_industry":[],

"position_environment":[]

};

#导航到目标网址

driver.get(url)

#计时器初始化

i =0

whileTrue:

#计时器累计计时:

i+=1

#获取当前页面DOM

pagecontent = driver.page_source

#解析HTML文档

result = etree.HTML(pagecontent)

#使用字典内单个list的extend方法累计收集数据

myresult["position_name"].extend(result.xpath('//ul[@class="item_con_list"]/li/@data-positionname'))

myresult["position_company"].extend(result.xpath('//ul[@class="item_con_list"]/li/@data-company'))

myresult["position_salary"].extend(result.xpath('//ul[@class="item_con_list"]/li/@data-salary'))

myresult["position_link"].extend(result.xpath('//div[@class="p_top"]/a/@href'))

myresult["position_exprience"].extend([ text.xpath('string(.)').strip()fortextinresult.xpath('//div[@class="p_bot"]/div[@class="li_b_l"]')])

myresult["position_industry"].extend([ text.strip()fortextinresult.xpath('//div[@class="industry"]/text()')])

myresult["position_environment"].extend(result.xpath('//div[@class="li_b_r"]/text()'))

#单次循环任务休眠

time.sleep(random.choice(range(3)))

#判断页面是否到尾部

ifresult.xpath('//div[@class="page-number"]/span[1]/text()')[0] !='30':

#如果未到达页面尾部,则点击下一页:

driver.find_element_by_xpath('//div[@class="pager_container"]/a[last()]').click()

#同时打印当前任务 状态!

print("第【{}】页抓取成功!".format(i))

else:

#如果所有页面到达尾部,则跳出循环!

break

#打印全局任务状态

print("everything is OK")

#退出并关闭selenium服务!

driver.quit()

#返回数据

returnpd.DataFrame(myresult)

运行抓取程序

url ="https://www.lagou.com/zhaopin"

mydata = getlaogou(driver,url)


欢迎关注天善智能www.hellobi.com,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

相关文章

网友评论

    本文标题:左手用R右手Python系列——动态网页抓取与selenium驱

    本文链接:https://www.haomeiwen.com/subject/bpafgxtx.html