เมื่อเร็ว ๆ นี้ ฉันค้นพบโครงการที่น่าสนใจมากบน GitHub: GitHub Link
ผู้เขียนผสมผสานเทคโนโลยี GPT
และ RPA
อย่างชาญฉลาดเพื่อสร้างตัวช่วยส่งเรซูเม่อัตโนมัติ นี่คือวิดีโอสาธิตเอฟเฟกต์ที่แชร์โดยผู้เขียนต้นฉบับ: ลิงก์วิดีโอสถานี B
อย่างไรก็ตาม โครงการเดิมมีปัญหาดังต่อไปนี้:
หลังจากดิ้นรนจนไม่เกิดประโยชน์ ฉันจึงตัดสินใจใช้ Node.js เพื่อนำโปรเจ็กต์กลับมาใช้ใหม่ ซึ่งไม่มีค่าใช้จ่ายใด ๆ ทั้งสิ้นและสามารถทำงานได้ในคลิกเดียวโดยไม่ต้องตั้งค่าเอเจนต์: ที่อยู่โปรเจ็กต์ GitHub
ในช่วงรับสมัครที่หนาวเย็นนี้ สคริปต์นี้สามารถให้ความช่วยเหลือและมอบความอบอุ่นให้กับคุณได้ หากคุณคิดว่าโครงการนี้มีคุณค่า ฉันหวังว่าคุณจะสามารถช่วยได้โดยการให้ดาว จะได้รับการชื่นชมอย่างมาก
ขั้นแรก เราจะใช้ selenium-webdriver เพื่อจำลองพฤติกรรมของผู้ใช้ ไลบรารีนี้เป็นเครื่องมือทดสอบอัตโนมัติที่ทรงพลัง ช่วยให้สามารถควบคุมการโต้ตอบของเบราว์เซอร์โดยทางโปรแกรม และมักใช้สำหรับงานต่างๆ เช่น การทดสอบอัตโนมัติ การดึงข้อมูลเว็บ และการจำลองการโต้ตอบของผู้ใช้
DOM
ของปุ่มเข้าสู่ระบบ จำลองการคลิกของผู้ใช้เพื่อทริกเกอร์การเข้าสู่ระบบ และรอให้ผู้ใช้สแกนโค้ด QRGPT
เพื่อรอการตอบกลับของ GPT
GPT
ตอบกลับ ให้คลิกปุ่ม "สื่อสารทันที" เพื่อเข้าสู่อินเทอร์เฟซการแชทการสื่อสารGPT
ส่งกลับลงในช่องแชท และทริกเกอร์เหตุการณ์การส่งผู้ที่พัฒนา GPT ไปแล้วควรรู้ว่าการเรียกอินเทอร์เฟซ GPT ต้องมีการชำระเงิน และขั้นตอนการเติมเงินนั้นยุ่งยากมากและต้องใช้บัตรธนาคารในต่างประเทศ
เพื่อให้กระบวนการนี้ง่ายขึ้น ฉันพบโปรเจ็กต์บน GitCode ที่ให้ API_KEY ฟรี ซึ่งสามารถรับได้อย่างง่ายดายโดยการเข้าสู่ระบบด้วยบัญชี GitHub
วิธีนี้คุณสามารถเริ่มต้นไคลเอนต์ OpenAI ด้วย API_KEY
ฟรี
// 初始化OpenAI客户端
const openai = new OpenAI ( {
// 代理地址,这样国内用户就可以访问了
baseURL : "https://api.chatanywhere.com.cn" ,
apiKey : "你的apiKey" ,
} ) ;
ในขั้นตอนนี้ สิ่งที่เราต้องการทำให้สำเร็จคือการเปิดเบราว์เซอร์และนำทางไปยัง URL ที่ระบุ การดำเนินการเฉพาะคือการเรียก API ของ selenium-webdriver และป้อนรหัสโดยตรง:
const { Builder , By , until } = require ( "selenium-webdriver" ) ;
const chrome = require ( "selenium-webdriver/chrome" ) ;
// 全局 WebDriver 实例
let driver ;
// 使用指定的选项打开浏览器
async function openBrowserWithOptions ( url , browser ) {
const options = new chrome . Options ( ) ;
options . addArguments ( "--detach" ) ;
if ( browser === "chrome" ) {
// 初始化一个谷歌浏览器客户端
driver = await new Builder ( )
. forBrowser ( "chrome" )
. setChromeOptions ( options )
. build ( ) ;
// 全屏打开浏览器
await driver . manage ( ) . window ( ) . maximize ( ) ;
} else {
throw new Error ( "不支持的浏览器类型" ) ;
}
await driver . get ( url ) ;
// 等待直到页面包含登录按钮dom
const loginDom = By . xpath ( "//*[@id='header']/div[1]/div[3]/div/a" ) ;
await driver . wait ( until . elementLocated ( loginDom ) , 10000 ) ;
}
// 主函数
async function main ( url , browserType ) {
try {
// 打开浏览器
await openBrowserWithOptions ( url , browserType ) ;
} catch ( error ) {
console . error ( `发生错误: ${ error } ` ) ;
}
}
const url =
"https://www.zhipin.com/web/geek/job-recommend?ka=header-job-recommend" ;
const browserType = "chrome" ;
main ( url , browserType ) ;
ในขั้นตอนนี้ เราจำเป็นต้องค้นหาโหนด DOM ของ ปุ่มเข้าสู่ระบบ จากนั้นจำลองการคลิกเพื่อเข้าสู่ระบบ
// 省略上一步的代码
// 点击登录按钮,并等待登录成功
async function logIn ( ) {
// 点击登录
const loginButton = await driver . findElement (
By . xpath ( "//*[@id='header']/div[1]/div[3]/div/a" )
) ;
await loginButton . click ( ) ;
// 等待微信登录按钮出现
const xpathLocatorWechatLogin =
"//*[@id='wrap']/div/div[2]/div[2]/div[2]/div[1]/div[4]/a" ;
await driver . wait (
until . elementLocated ( By . xpath ( xpathLocatorWechatLogin ) ) ,
10000
) ;
const wechatButton = await driver . findElement (
By . xpath ( "//*[@id='wrap']/div/div[2]/div[2]/div[2]/div[1]/div[4]/a" )
) ;
// 选择微信扫码登录
await wechatButton . click ( ) ;
const xpathLocatorWechatLogo =
"//*[@id='wrap']/div/div[2]/div[2]/div[1]/div[2]/div[1]/img" ;
await driver . wait (
until . elementLocated ( By . xpath ( xpathLocatorWechatLogo ) ) ,
10000
) ;
// 等待用户扫码,登录成功
const xpathLocatorLoginSuccess = "//*[@id='header']/div[1]/div[3]/ul/li[2]/a" ;
await driver . wait (
until . elementLocated ( By . xpath ( xpathLocatorLoginSuccess ) ) ,
60000
) ;
}
// 主函数
async function main ( url , browserType ) {
try {
// 打开浏览器
// 点击登录按钮,并等待登录成功
+ await logIn ( ) ;
} catch ( error ) {
console . error ( `发生错误: ${ error } ` ) ;
}
}
หลังจากเข้าสู่ระบบสำเร็จแล้ว คุณจะเข้าสู่หน้ารายการข้อมูลการรับสมัคร ในขั้นตอนนี้ เราจำเป็นต้องสำรวจข้อมูลการรับสมัคร และคลิก เพื่อค้นหาข้อมูลลักษณะงานของข้อมูลการรับสมัครแต่ละรายการ ดังแสดงในรูป:
// 省略上一步的代码
// 根据索引获取职位描述
async function getJobDescriptionByIndex ( index ) {
try {
const jobSelector = `//*[@id='wrap']/div[2]/div[2]/div/div/div[1]/ul/li[ ${ index } ]` ;
const jobElement = await driver . findElement ( By . xpath ( jobSelector ) ) ;
// 点击招聘信息列表中的项
await jobElement . click ( ) ;
// 找到描述信息节点并获取文字
const descriptionSelector =
"//*[@id='wrap']/div[2]/div[2]/div/div/div[2]/div/div[2]/p" ;
await driver . wait (
until . elementLocated ( By . xpath ( descriptionSelector ) ) ,
10000
) ;
const jobDescriptionElement = await driver . findElement (
By . xpath ( descriptionSelector )
) ;
return jobDescriptionElement . getText ( ) ;
} catch ( error ) {
console . log ( `在索引 ${ index } 处找不到工作。` ) ;
return null ;
}
}
// 主函数
async function main ( url , browserType ) {
try {
// 打开浏览器
// 点击登录按钮,并等待登录成功
// 开始的索引
+ let jobIndex = 1 ;
+ while ( true ) {
+ // 获取对应下标的职位描述
+ const jobDescription = await getJobDescriptionByIndex ( jobIndex ) ;
+ console . log ( `职位描述信息/n: ${ jobDescription } ` ) ;
+ if ( jobDescription ) {
+ //
+ }
+ jobIndex += 1 ;
}
} catch ( error ) {
console . error ( `发生错误: ${ error } ` ) ;
}
}
จากนั้นรวมข้อมูลเรซูเม่ที่อัปโหลดและข้อมูลการรับสมัครแล้วส่งต่อไปยัง GPT
รอการตอบกลับจาก GPT
:
// 省略上一步的代码
// 读取简历信息
const getResumeInfo = ( ) => {
fs . readFile ( "./简历基本信息.txt" , "utf8" , ( err , data ) => {
if ( err ) {
console . error ( "读取文件时出错:" , err ) ;
return ;
}
// 输出文件内容
return data ;
} ) ;
} ;
// 与GPT进行聊天的函数
async function chat ( jobDescription ) {
// 获取简历信息
const resumeInfo = getResumeInfo ( ) ;
const askMessage = `你好,这是我的简历: ${ resumeInfo } ,这是我所应聘公司的要求: ${ jobDescription } 。我希望您能帮我直接给HR写一个礼貌专业的求职新消息,要求能够用专业的语言将简历中的技能结合应聘工作的描述,来阐述自己的优势,尽最大可能打动招聘者。并且请您始终使用中文来进行消息的编写,开头是招聘负责人。这是一封完整的求职信,不要包含求职信内容以外的东西,例如“根据您上传的求职要求和个人简历,我来帮您起草一封求职邮件:”这一类的内容,以便于我直接自动化复制粘贴发送,字数控制在80字左右为宜` ;
try {
const completion = await openai . chat . completions . create ( {
messages : [
{
role : "system" ,
content : askMessage ,
} ,
] ,
model : "gpt-3.5-turbo" ,
} ) ;
// 获取gpt返回的信息
const formattedMessage = completion . choices [ 0 ] . message . content . replace (
/ n / g ,
" "
) ;
return formattedMessage ;
} catch ( error ) {
console . error ( `gpt返回时发生错误: ${ error } ` ) ;
const errorResponse = JSON . stringify ( { error : String ( error ) } ) ;
return errorResponse ;
}
}
// 主函数
async function main ( url , browserType ) {
try {
// 打开浏览器
// 点击登录按钮,并等待登录成功
// 开始的索引
while ( true ) {
// 获取对应下标的职位描述
if ( jobDescription ) {
// 发送描述到聊天并打印响应
+ const response = await chat ( jobDescription ) ;
+ console . log ( "gpt给的回复" , response ) ;
}
jobIndex += 1 ;
}
} catch ( error ) {
console . error ( `发生错误: ${ error } ` ) ;
}
}
หลังจากการตอบกลับ GPT เสร็จสิ้น ให้ค้นหา ปุ่มสื่อสารทันที และจำลองการคลิก ในเวลานี้ คุณจะเข้าสู่อินเทอร์เฟซการสื่อสารและการแชท ดังแสดงในรูป:
// 省略上一步的代码
// 主函数
async function main ( url , browserType ) {
try {
// 打开浏览器
// 点击登录按钮,并等待登录成功
// 开始的索引
while ( true ) {
// 获取对应下标的职位描述
if ( jobDescription ) {
// 发送描述到聊天并打印响应
// 点击沟通按钮
+ const contactButton = await driver . findElement (
+ By . xpath (
+ "//*[@id='wrap']/div[2]/div[2]/div/div/div[2]/div/div[1]/div[2]/a[2]"
+ )
+ ) ;
+ await contactButton . click ( ) ;
}
jobIndex += 1 ;
}
} catch ( error ) {
console . error ( `发生错误: ${ error } ` ) ;
}
}
ณ จุดนี้ ให้เข้าสู่อินเทอร์เฟซการแชท กรอกข้อมูลการส่งคืน GPT ลงในช่องป้อนข้อมูล และทริกเกอร์เหตุการณ์การส่ง
// 省略上一步的代码
// 发送响应到聊天框
async function sendResponseToChatBox ( driver , response ) {
try {
// 请找到聊天输入框
const chatBox = await driver . findElement ( By . xpath ( "//*[@id='chat-input']" ) ) ;
// 清除输入框中可能存在的任何文本
await chatBox . clear ( ) ;
// 将响应粘贴到输入框
await chatBox . sendKeys ( response ) ;
await sleep ( 1000 ) ;
// 模拟按下回车键来发送消息
await chatBox . sendKeys ( Key . RETURN ) ;
await sleep ( 2000 ) ; // 模拟等待2秒
} catch ( error ) {
console . error ( `发送响应到聊天框时发生错误: ${ error } ` ) ;
}
}
// 主函数
async function main ( url , browserType ) {
try {
// 打开浏览器
// 点击登录按钮,并等待登录成功
// 开始的索引
while ( true ) {
// 获取对应下标的职位描述
if ( jobDescription ) {
// 发送描述到聊天并打印响应
// 点击沟通按钮
// 等待回复框出现
+ const chatBox = await driver . wait (
+ until . elementLocated ( By . xpath ( "//*[@id='chat-input']" ) ) ,
+ 10000
+ ) ;
+ // 调用函数发送响应
+ await sendResponseToChatBox ( driver , response ) ;
+ // 返回到上一个页面
+ await driver . navigate ( ) . back ( ) ;
+ await sleep ( 2000 ) ; // 模拟等待3秒
}
jobIndex += 1 ;
}
} catch ( error ) {
console . error ( `发生错误: ${ error } ` ) ;
}
}
หลังจากส่งแล้ว ให้กลับไปที่หน้ารายการรับสมัครงานและทำซ้ำขั้นตอนนี้
โปรเจ็กต์นี้เพียงส่งข้อมูลเรซูเม่รวมกับข้อมูลงานไปที่ GPT แล้วส่ง GPT ตอบกลับไปยังผู้สรรหา จริงๆ แล้วไม่ใช่เรื่องยากและมีวัตถุประสงค์เพื่อดึงดูดแนวคิดใหม่ๆ
จริงๆ แล้วมีวิธีที่หรูหรากว่านี้ เช่น ส่งเรซูเม่ของคุณไปที่ GPT และปล่อยให้ GPT ดึงข้อมูลที่มีประสิทธิภาพ (นี่คือสิ่งที่ผู้เขียนต้นฉบับทำ) อย่างไรก็ตาม เนื่องจากโครงการที่ไม่มี GPT-API ไม่มีบริการช่วยเหลือ จึงจำเป็นต้องชำระเงินเพื่อให้บรรลุเป้าหมายนี้ เพื่อนๆ ที่มีช่องทางการเติมเงินสามารถลองใช้ได้
นอกจากนี้สำหรับผู้ที่สนใจสามารถเจาะลึกได้อีก เช่น
สุดท้ายนี้ ฉันขอย้ำมุมมองของผู้เขียนต้นฉบับ:
ฉันหวังว่าจะไม่มีใครใช้สคริปต์ของฉันในการตัดกระเทียม พวกเขาถูกบังคับให้ใช้สคริปต์นี้เพื่อส่งเรซูเม่แล้ว ไม่มีอะไรเหลือให้บีบออกมา