**注意:**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开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
文末有福利领取哦~
👉一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
👉二、Python必备开发工具
👉三、Python视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
👉 四、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。(文末领读者福利)
👉五、Python练习题
检查学习结果。
👉六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
👉因篇幅有限,仅展示部分资料,这份完整版的Python全套学习资料已经上传
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
(文末领读者福利)**
👉五、Python练习题
检查学习结果。
👉六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
👉因篇幅有限,仅展示部分资料,这份完整版的Python全套学习资料已经上传
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算