看一下任务要求 1. 搜索页输入关键词,点击搜索按钮 2. 列表页内容提取 (正则表达式 + Json)[输入关键字 拿到输入后的第一个页面] 3. 详情页内容提取 (Selenium + XPath)[页面中再点开具体内容 然后显示内容] 4. 保存数据到Excel表
(零)预备环节
(1)先看看要分别引入多少库
from selenium import webdriver (网页抓取)
from selenium.common.exceptions import TimeoutException (用于异常排查)
from selenium.webdriver.common.by import By (用于元素定位)
from selenium.webdriver.support import expected_conditions as EC (用于显示等待)
from selenium.webdriver.support.wait import WebDriverWait (用于反屏蔽中设置等待时间)
from os import makedirs (新建目录的方法)
from os.path import exists
import json (处理可能遇到的json文件)
import re (编写正则表达式)
import pandas as pd (编写pandas用dataframe保存到excel)
(2)看看用到哪些全局变量(网址、爬取页数、文件夹名、文件具体名)
INDEX_URL = 'https://www....com/' #网址
TIMEOUT = 10 # 超时10秒
TOTAL_PAGE = 10 # 共爬取10页
RESULTS_DIR = 'results' # 结果文件夹
RESULTS_FILE = 'jobs.xlsx'#具体文件夹的文件名
exists(RESULTS_DIR) or makedirs(RESULTS_DIR) # 文件夹不存在就新建 有就放 没有就建
(3)反屏蔽设置[这个以后直接复制粘贴用 不用详细了解]
# 反屏蔽选项设置
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)
browser = webdriver.Chrome(options=options)
wait = WebDriverWait(browser, TIMEOUT)
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
#以上是返屏蔽操作 了解
(一)输入关键字 并且点击按钮
先看我自己操作的逻辑
browser.get(INDEX_URL)
inputBox=browser.find_element(By.ID,"kwdselectid") #打开网址后定位到当前文本框
keyword=input("请输入你要搜索的关键字")
inputBox.send_keys(f'{keyword}') #巧妙 先放一个input 再用f"{}"将变量进行替换
time.sleep(2)
search=wait.until(EC.element_to_be_clickable((By.XPATH,"//div[@class='ush top_wrap']/button"))) #这个存贮方式不是id和class,那么我就用Xhelperl拿到对应的路径
search.click() #模拟点击操作
wait.until(EC.presence_of_element_located((By.CLASS_NAME,'footer'))) #我们发现仅仅上面那样做是不够的 没有返回值对象,再进行等待
html=browser.page_source #这个拿到的是下一页的内容源码
(1)对已配置好的brower放置网址
(2)想输入 那就定义对应的文本框 发现id的方法简单,就用了id的搜索
(3)为了更加自由 设置input 放置输入内容
(4)再次是send_keys函数 相当于把你在程序里面的input输送给浏览器 涉及f'{keyword}'又是f和花括号用以变量引用
(5)完事后休息2秒 2秒后再执行下一步点击操作
(6)先获取点击的节点,在进行对应的点击操作,这个时候用了显示等待,为的是能有时间让计算机获取服务器发来的信息
(7)模拟点击命令
(8)这一步就更巧妙 为了确保最后一步能够拿到source 再加一个等待条件:
直到页面底部元素才进行下一步==直到下个页面加载完成 才开始挖掘source内容
如果没有这一步,刚刚点击就要立刻返回数据,可能页面没有跳转,其实也拿不到数据
实际来看,没有这个步骤确实拿不到source
(9)获取一下服务器返回的page_source
PS:下面贴出老师做的版本
# TODO 1. 爬取首页 返回源代码数据 (目的就是在任务栏快速定位代码)
def crawlIndex():
html=''
try:
browser.get(INDEX_URL)
inputBox=browser.find_element(By.ID,"kwdselectid") #打开网址后定位到当前文本框
except TimeoutException:
print("访问超时")
keyword=input("请输入你要搜索的关键字")
# keyword='python'
inputBox.send_keys(f'{keyword}') #巧妙 先放一个input 再用f"{}"将变量进行替换
time.sleep(2)
try: #在下面尝试搜索功能 这里用显示等待 如果成立就点击完继续执行
search=wait.until(EC.element_to_be_clickable((By.XPATH,"//div[@class='ush top_wrap']/button"))) #这个存贮方式不是id和class,那么我就用Xhelperl拿到对应的路径
search.click() #模拟点击操作
#这个footer用ctrl+f看一下发现是 页面尾部的内容 一般这个加载出来表示整个页面也加载完成 所以要找这个属性
wait.until(EC.presence_of_element_located((By.CLASS_NAME,'footer'))) #我们发现仅仅上面那样做是不够的 没有返回值对象,再进行等待
html=browser.page_source #这个拿到的是下一页的内容源码
except TimeoutException:
print("访问超时")
#为了方便测试数据解析效果,将获取到的列表页源代码保存在本地文件中
# with open(f"{RESULTS_DIR}/51job_list.html","w",encoding="utf-8")as f: #先找到文件夹 再找到目标文件
# f.write(html)
return html
(二)提取我需要的岗位具体内容(工资、地点、要求...)
(1)一般信息会直接分散存放在网页源代码之中,但是这次观察网页源代码发现其实并没有这些信息。但是ctrl+f发现,这些工作岗位集中出现在472行代码之中,那思路就是先提取定位到472行内容,看看是什么情况
jobinfo=re.search('window.__SEARCH_RESULT__ =(.*)</script>',html) #发现一个问题 输入我们想要的职位 出现在472行代码 window.__SEARCH_RESULT__ = {"top_ads":[],"a...的内容里
#print(jobinfo.group(1))
(2)正则提取目标行的内容,发现是一个字典形式的json文件,打印第一个group看看内容,发现内容还是很多,这个时候放在json在线分析网站再整理节点,发现全部保存在“engine_jds”这个分支下面,那就转化为字典,通过键值对的形式分析我们需要的数据。
jobinfo_dict=json.loads(jobinfo.group(1)) #进行类型转换 变成字典形式
jobs=jobinfo_dict['engine_jds'] #既然数据都存在字典里面 那我给你健 你要给我值
(3)下面的处理就变成字典的处理了,没毛病,直接按键取值
建一个空列表放置对应内容文章来源:https://www.toymoban.com/news/detail-448820.html
jobItem = [] # 保存一条工作信息
jobItem.append(job['jobid']) # 工作编码 相当于字典的形式 你给我键 我给你值 然后往里面添加
jobItem.append(job['providesalary_text']) # 工资待遇
jobItem.append(job['workarea_text']) # 工作地点
if len(job['attribute_text']) == 3:
jobItem.append(job['attribute_text'][1]) # 标签文本:经验要求
jobItem.append(job['attribute_text'][2]) # 标签文本:学习要求
elif len(job['attribute_text']) == 2:
jobItem.append(job['attribute_text'][1]) # 标签文本:经验要求
jobItem.append('')
else:
jobItem.append('')
jobItem.append('')
jobItem.append(job['job_href']) # 详情页链接
jobItem.append(job['company_name']) # 公司名称
jobItem.append(job['companysize_text']) # 公司规模
jobItem.append(job['companytype_text']) # 公司类别
if job['jobwelf']:
jobItem.append(job['jobwelf']) # 公司福利
else:
jobItem.append('')
obItem.append(job['companyind_text']) # 主营业务
jobItem.append(job['updatedate']) # 发布日期
jobItem.append(job['company_href']) # 公司介绍页链接
# print(len(jobItem))
jobItems.append(jobItem) # 将1条信息添加到工作信息表中
(四)直接保存一下这个列表页 还是用pd的方法保存,定义保存在二维列表中文章来源地址https://www.toymoban.com/news/detail-448820.html
header=['工作编码', '工作名称', '工资待遇', '工作地点', '经验要求', '学历要求', '详情页链接', '公司名称', '公司规模', '公司类别', '公司福利', '主营业务', '发布日期',
'公司介绍页链接']
df=pd.DataFrame(data,columns=header) #定义这个二维列表
df.to_excel(f"{RESULTS_DIR}/{RESULTS_FILE}",index=False,header=header)
#成功 这个时候所有文件都保存到了本地
到了这里,关于selenium的项目实战详解(单一详情页面处理)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!