selennium实战详解(1),Python岗面试12家大厂成功跳槽

**注意:**entrancce的两个参数由主函数传递进来。每执行一段程序建议休眠一段时间,休眠时长根据自身网络配置自行调整。

主函数添加这行代码:

运行后就能对进行拉勾初步访问了

2.2.4构建爬取一级页面信息函数

构建名为get_information的函数,用于爬取一级页面的招聘信息。现在,我要爬取这些数据

岗位名称, 月薪,公司名称,公司福利,经验要求,学历要求六项数据。

首先选中岗位名称右键检查发现这个元素的父节点在class名为‘p-top_1F7CL’ 的节点下

我们复制名称发现可以找到15个元素,有爬取经验的话你就会发现这里刚好是一页的数据,所以我们名称可以通过这个节点查找,至于方法,即可用xpath也可用class_name的方法。同理,我们公司名,福利,月薪等都能用这个方式获取,唯一不同的是

经验跟学历在组成同一个文本,要用split()的方法对他们进行分割。而这以这两者的合并的字符串文本又跟月薪的父节点在同一节点下,但月薪有标签,经验学历要求没有。之前我们说过:如果使用selenium的find_element的方法获取目标路径的文本会获取递归获取所有文本,包括子节点的文本。也就是说获取经验学历要求必须通过获取div节点位置再以.text形式输出,但输出的内容不仅有经验学历要求,还有月薪,因此要用replace函数对数据进行去重。

获取该节点的所有文本,其中包括有月薪,学历要求, 工作要求

info = driver.find_elements_by_xpath(‘//div[@class=“p-bom__JlNur”]’)

salary = driver.find_elements_by_xpath(‘//div[@class=“p-bom__JlNur”]/span’)

因为月薪是跟学历/工作要求的父节点在同一父节点下的文本文件,而selenium的.text方法是提取目标路径下的所有文本,包括子节点的文本,所以会有数据重复,要去重

for i in range(len(name)): # len(name)表示有多少条招聘信息

s = info[i].text.replace(salary[i].text, “”)

edu_requirements = s.split(" / ")[0]

exp_requirements = s.split(" / ")[1]

所以现在获取一级页面的招聘信息的任务就结束了。完整的代码如下:

def get_information():

1.selenium的find_elements_by_xpath不支持直接获取目标属性值

2.因为一页不止一个招聘数据,所以不能用element只能用elements

3.elements里面的元素是selenium标记的元素地址

4.因为elements返回的是列表,而列表没有get_attribute属性,所以要获取所有与目标属性相同节点下的路径,再对其遍历

name = driver.find_elements_by_xpath(‘//div[@class=“p-top__1F7CL”]/a’)

companyName = driver.find_elements_by_xpath(‘//div[@class=“company-name__2-SjF”]/a’)

welfare = driver.find_elements_by_xpath(‘//div[@class=“il__3lk85”]’)

获取该节点的所有文本,其中包括有月薪,学历要求, 工作要求

info = driver.find_elements_by_xpath(‘//div[@class=“p-bom__JlNur”]’)

salary = driver.find_elements_by_xpath(‘//div[@class=“p-bom__JlNur”]/span’)

因为月薪是跟学历/工作要求的父节点在同一父节点下的文本文件,而selenium的.text方法是提取目标路径下的所有文本,包括子节点的文本,所以会有数据重复,要去重

for i in range(len(name)): # len(name)表示有多少条招聘信息

s = info[i].text.replace(salary[i].text, “”)

edu_requirements = s.split(" / ")[0]

exp_requirements = s.split(" / ")[1]

print(name[i].text, companyName[i].text, welfare[i].text, salary[i].text, edu_requirements,

exp_requirements)

完成这部分的代码后要在entrance函数那里添加这个函数进去就能被调用了。

**附:**如果你闲着无聊想爬一下浮窗的信息

我可以满足你,你可以参考一下这段代码

# 鼠标悬停至招聘信息中,获取二级页面简略信息

move = driver.find_elements_by_xpath(‘//div[@class=“item__10RTO”]’)

h = 50

for i in move:

print(move.index(i))

# driver.execute_script(“arguments[0].scrollIntoView();”, i) # 将滚动条移动到可以显示元素位置

ActionChains(driver).move_to_element(i).perform()

time.sleep(2)

j = driver.find_element_by_xpath(‘//div[@class=“job_info__rB-X6 job_desr_max__N_INq”]’)

print(j.text)

time.sleep(2)

# 滑动滚动条,参数可以根据窗体大小适当调整scroll(左边距,上边距)

driver.execute_script(“scroll(0,%s)” % str(100 + h))

h += 100

他出现弹窗的条件还是比较苛刻的,要鼠标停留在这条招聘信息才能显示,而且要在可视范围。就以上面那张图为例,就显示了三条招聘信息,所以最多只能停留在三个位置获取浮窗信息然后就要滑动滚动条了。上面代码有两种方法可以滑动,第一个就是用专门滑动的方法将滚动条定位在元素出现的位置。我用的话很鸡肋,经常对不上。第二种就是自定义增加滑动尺度了,这个不够智能,也许你要调试很多次才能找到每次元素向下移动的距离。这里我附上我成功爬下来的截图。

浮窗信息会损失一部分内容,即使获取下来也没有太大用处 。

2.2.5构建driver设置函数

构建名为driver_setting的函数,用于设置driver相关参数。我们每次确定爬取是否成功都要看他是否能输出招聘信息,而driver初始化是在左上角往下,会挡住控制台输出,所以我们设置一下他的初始大小跟初始位置。

def driver_setting():

缩放也要注意格式,不然发生点击事件时可能会报错

设置初始位置

driver.set_window_position(x=500, y=0)

设置初始大小

driver.set_window_size(width=1050, height=900, windowHandle=‘current’)

设置全屏

driver.maximize_window()

然后在主函数添加这个设置即可。

那么下次启动后将会出现在屏幕右侧。

2.2.6构建爬取二级页面数据函数

构建名为detail_info函数用于爬取二级页面详情信息。现在进入二级页面,在这里我们爬取

职位描述跟工作地点。

选中职位描述右击检查发现这些信息在class名为‘job-detail’的节点下。找到xpath路径之后用find_element().text的方法即可获取该节点下的所有文本信息

我们多看几个详情信息会发现有些节点是在class名为‘job-detail’的节点下面还有一个节点p英所以要爬取两种情况的信息,然后舍弃掉长度为0的信息。对于地址信息,可以获取名为"work_addr"的class节点下的所有信息然后去掉最后5个字符‘\n查看地图’

完整代码如下:

def detail_info():

print(“successfully loading”)

获取’//div[@class=“work_addr”]'下的文本。跟xpath不同的是selenium递归获取该节点所有文本包括节点下面节点的文本;同一根节点下的所有文本归为一个文本元素

ad = driver.find_elements_by_xpath(‘//div[@class=“work_addr”]’) # 详细地址

for i in ad: # 即使elements里面只有一个元素也不能直接ad.text获取元素文本信息

address = i.text.strip()[:-5] # 除去最后的’\n查看地图’

因为职位描述xpath路径不一,所以要判断有可能出现的情况

information1 = driver.find_elements_by_xpath(‘//div[@class=“job-detail”]’)

information2 = driver.find_elements_by_xpath(‘//div[@class=“job-detail”]/p’)

information = “”

对职位描述进行拼接

if information1:

for i in information1:

information += i.text.strip()

else:

for i in information2:

information += i.text.strip()

print(address)

print(information)

2.2.7定义二级页面访问接口

定义名为relay的函数,它是一级页面访问二级页面的接口。另外定义这个接口是为了提高加载速度。我们用了句柄。先同时加载一页的所有二级界面,然后再切换句柄进行爬取并关闭。在使用for点击name的时候用了try-except避免没有加载成功的情况。完整代码如下:

定义二级页面访问接口

def relay(name):

句柄确定主界面,即一级界面

first_handle = driver.current_window_handle

点击访问二级页面

for i in name:

若没有点击成功,则休眠两秒继续点击

try:

i.click()

except:

time.sleep(2)

i.click()

time.sleep(1)

all_handles = driver.window_handles

遍历所有句柄进行爬取

for handle in all_handles:

if handle != first_handle:

切换句柄

driver.switch_to.window(handle)

爬取二级页面信息

detail_info()

time.sleep(1)

爬取成功后关闭句柄

driver.close()

time.sleep(2)

等所有二级界面爬取完后返回一级界面

driver.switch_to.window(first_handle)

然后在get_information声明调用。

2.2.8 定义翻页函数

构建名为next_page的函数,用于实现翻页功能。为模拟翻页,我们要找到翻页的那个按钮然后点击它。右击检查下一页按钮找到该元素在源码中的位置。

然后点击即可。注意:点击翻页的过程中可能会因为出现浮窗,浏览器缩放,元素未更新等情况导致点击失败。所以要用time.sleep+滑动滚动条或者调整浏览器大小的方法避免出现上述情况。点击完下一页后调用get_information函数继续爬取招聘信息。当没有找到元素时说明已经到了尾页,没有下一页了,此时用try-except捕获异常并输出

具体代码如下:

def next_page():

driver.find_element_by_class_name(“pager_next”).click()

time.sleep(3)

使用try-except避免未找到元素报错

try:

pager_next = driver.find_element_by_class_name(“lg-pagination-next”)

driver.execute_script(“scroll(0,2500)”) # 下拉滚动条,拉到底,不然会有弹窗影响点击,然后就报错,我这里卡了好久

driver.find_element_by_class_name(“lg-pagination-next”).click()

time.sleep(2)

get_information()

except:

没有下一页时则直接关闭

print(“爬取完毕!”)

close()

现在有个问题就是:该在哪里调用下一页函数呢?应该在relay接口那里调用

为什么要在这里调用?因为这个接口切换了句柄。必须要将句柄切换回一级界面之后才能调用翻页函数,否则会找不到翻页的元素,然后报错。

2.2.9构建保存数据函数

这里我们是使用openpyxl库来将数据导出到excel。首先构建initialize_xlsx函数用于初始化excel表。如加入表头,居中对齐,然后再美化一下字体等。对于默认单元格来说,是无法将很多数据显示全的,因此我们还要调宽一下单元格。我们结合代码分析一下:

def initialize_xlsx():

title = [‘职业名称’, ‘公司名称’, ‘公司福利’, ‘薪水范围’, ‘经验要求’, ‘学历要求’, ‘详细地址’, ‘详情信息’]

sheet.append(title)

设置第 1 行的高度

sheet.row_dimensions[1].height = 30

设置字体样式

font = Font(name=“微软雅黑”, size=15, bold=True)

设置对齐样式-水平对齐方式,垂直对齐方式,字体倾斜度,是否换行

alignment = Alignment(horizontal=“center”, vertical=“center”, text_rotation=45, wrap_text=True)

试了一下不能直接通过’A1:F1’来进行批量设置,所以只能一个一个来了

for i in range(1, len(title) + 1):

chr表示将对应Unicode编码数字的字符串表示出来 如 chr(65) = ‘A’

i = chr(64 + i)

cell = sheet[i + ‘1’] # 表示从A1开始

cell.font = font

设置对应列的宽度

sheet.column_dimensions[i].width = 42

cell.alignment = alignment

设置保存路径

workbook.save(filename=‘C:\Users\17591\Desktop\lagou.xlsx’)

其实我们先说上面的代码是不严谨的,应该要先创建workbook对象,我们在主函数创建。有两种写入方式,第一种就是覆盖式写入,第二种是追加式写入。按自己的喜欢的方式创建。追加式写入的话必须要先创建有excel。我的话我选择了覆盖式写入。在主函数添加如下代码:

追加式写入

workbook = load_workbook(filename=‘C:\Users\17591\Desktop\lagou.xlsx’)

print(workbook.sheetnames)

sheet = workbook[‘employment_information’]

覆盖式写入

workbook = openpyxl.Workbook()

sheet = workbook.active

设置工作表名

sheet.title = ‘employment_information’

添加完后再调用initialize_xlsx函数

构建名为write_xlsx的函数,用于保存一级界面爬取的招聘信息。

def write_xlsx(data):

将数据在excel尾部插入

sheet.append(data)

将数据保存至目标工作目录。前面我们是使用覆盖式写入的方法,所以工作目录不存在时会新建一个

workbook.save(filename=‘C:\Users\17591\Desktop\lagou.xlsx’)

前面我们已经完成了一级界面的数据爬取与打印,现在我们就将write_xlsx函数添加在打印的下方即可。

构建名为write_detail的函数用于保存二级界面爬取的数据。

(红框就是我们将要保存的信息。)

可以看到我们要将二级页面的数据加入到一级页面数据的后方。但是sheet.append()的方法是在最近没有写入数据的一行写入数据。就是说无论你第一行有多少列数据,只要一列有数据,那么append就只能添加到下一行,如果第二行也有数据就添加到第三行以此类推。因此我们不能简单的用append()的方法写入数据,要定义一个全局变量的索引,用于确定添加元素的位置,每添加一行索引就加一。有了这思路就好办了,直接上代码

def write_detail(data):

同样要声明全局变量

global index

print(index)

二级页面的数据刚好从G列开始保存

sheet[‘G’ + str(index)] = data[0]

sheet[‘H’ + str(index)] = data[1]

index += 1

workbook.save(filename=‘C:\Users\17591\Desktop\lagou.xlsx’)

然后在主函数里声明全局变量

同样的,在detail_info函数里调用它

到这里,我们算是完成了本次案例,看一下excel的效果图。

3.完整代码

=======

虽然呢这里有现成的代码,但我还是建议同学们先理解了之后再查阅。

import time

from selenium.webdriver.common.action_chains import ActionChains

import openpyxl

from openpyxl.styles import Font, Alignment

from selenium import webdriver

def entrance(urls, kws):

driver.get(urls)

time.sleep(2)

注意elements 与 element的区别 elements返回的是列表,无法点击

driver.find_element_by_xpath(‘//*[@id=“changeCityBox”]/ul/li[6]/a’).click() # 切换至深圳站,因为深圳IT岗位较多,新版拉勾切换了没用,所以随便点

ipt = driver.find_element_by_id(“search_input”)

ipt.send_keys(kws)

time.sleep(2)

driver.find_element_by_id(“search_button”).click()

time.sleep(2)

get_information()

def get_information():

1.selenium的find_elements_by_xpath不支持直接获取目标属性值

2.因为一页不止一个招聘数据,所以不能用element只能用elements

3.elements里面的元素是selenium标记的元素地址

4.因为elements返回的是列表,而列表没有get_attribute属性,所以要获取所有与目标属性相同节点下的路径,再对其遍历

name = driver.find_elements_by_xpath(‘//div[@class=“p-top__1F7CL”]/a’)

companyName = driver.find_elements_by_xpath(‘//div[@class=“company-name__2-SjF”]/a’)

welfare = driver.find_elements_by_xpath(‘//div[@class=“il__3lk85”]’)

获取该节点的所有文本,其中包括有月薪,学历要求, 工作要求

info = driver.find_elements_by_xpath(‘//div[@class=“p-bom__JlNur”]’)

salary = driver.find_elements_by_xpath(‘//div[@class=“p-bom__JlNur”]/span’)

因为月薪是跟学历/工作要求的父节点在同一父节点下的文本文件,而selenium的.text方法是提取目标路径下的所有文本,包括子节点的文本,所以会有数据重复,要去重

for i in range(len(name)): # len(name)表示有多少条招聘信息

s = info[i].text.replace(salary[i].text, “”)

edu_requirements = s.split(" / ")[0]

exp_requirements = s.split(" / ")[1]

print(name[i].text, companyName[i].text, welfare[i].text, salary[i].text, edu_requirements,

exp_requirements)

将信息写入xlsx表格

write_xlsx([name[i].text, companyName[i].text, welfare[i].text,

salary[i].text, edu_requirements, exp_requirements])

转自访问二级页面接口

time.sleep(2)

将招聘名称列表传入,用于点击

relay(name)

————————————————————————————————————————————————————————————————————————————

# 鼠标悬停至招聘信息中,获取二级页面简略信息

move = driver.find_elements_by_xpath(‘//div[@class=“item__10RTO”]’)

h = 50

for i in move:

print(move.index(i))

# driver.execute_script(“arguments[0].scrollIntoView();”, i) # 将滚动条移动到可以显示元素位置

ActionChains(driver).move_to_element(i).perform()

time.sleep(2)

j = driver.find_element_by_xpath(‘//div[@class=“job_info__rB-X6 job_desr_max__N_INq”]’)

print(j.text)

time.sleep(2)

# 滑动滚动条,参数可以根据窗体大小适当调整scroll(左边距,上边距)

driver.execute_script(“scroll(0,%s)” % str(100 + h))

h += 100

定义二级页面访问接口

def relay(name):

句柄确定主界面,即一级界面

first_handle = driver.current_window_handle

点击访问二级页面

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

文末有福利领取哦~

👉一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。img

👉二、Python必备开发工具

img
👉三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
img

👉 四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。(文末领读者福利)
img

👉五、Python练习题

检查学习结果。
img

👉六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
img

img

👉因篇幅有限,仅展示部分资料,这份完整版的Python全套学习资料已经上传

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

(文末领读者福利)**
img

👉五、Python练习题

检查学习结果。
img

👉六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
img

img

👉因篇幅有限,仅展示部分资料,这份完整版的Python全套学习资料已经上传

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值