-
-
Save stepney141/329ef8b5be55b2d355831109f7eced48 to your computer and use it in GitHub Desktop.
履修ポチポチ楽しい!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LOYOLA_ID=A1234567 | |
LOYOLA_PASSWORD=password |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const puppeteer = require('puppeteer'); | |
const path = require('path'); | |
require('dotenv').config({ path: path.join(__dirname, "./.env") }); //認証情報は別ファイルから読み込む | |
const setting = { | |
loyola_id: process.env.LOYOLA_ID, //学籍番号 | |
loyola_password: process.env.LOYOLA_PASSWORD, //パスワード | |
loyola_uri: "https://scs.cl.sophia.ac.jp/campusweb/campusportal.do", | |
}; | |
const loyola_xpath = { | |
login_username: '//input[@name="userName"]', | |
login_password: '//input[@name="password"]', | |
login_button: '//input[@value="ログイン"]', | |
time_extension_clock: '//*[@id="portaltimer"]', //時間延長ボタン | |
button_of_curriculum_menu: '//*[@id="tab-rs"]', //ホーム画面ヘッダーのカリキュラム/履修登録メニューのアイコン | |
}; | |
// ref: https://qiita.com/albno273/items/c2d48fdcbf3a9a3434db | |
// example: await sleep(randomWait(1000, 0.5, 1.1)); 1000ms x0.5 ~ x1.1 の間でランダムにアクセスの間隔を空ける | |
const sleep = async (time) => new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, time); }); | |
const randomWait = (baseWaitSeconds, min, max) => baseWaitSeconds * (Math.random() * (max - min) + min); | |
const login = async (page) => { | |
try { | |
await page.goto(setting.loyola_uri, { //LOYOLAトップページに飛ぶ | |
waitUntil: 'domcontentloaded', | |
}); | |
const userNameInputHandle = await page.$x(loyola_xpath.login_username); | |
const passwordInputHandle = await page.$x(loyola_xpath.login_password); | |
const loginButtonHandle = await page.$x(loyola_xpath.login_button); | |
await userNameInputHandle[0].type(setting.loyola_id); //学籍番号入力 | |
await passwordInputHandle[0].type(setting.loyola_password); //パスワード入力 | |
await Promise.all([ | |
page.waitForNavigation({ waitUntil: ["domcontentloaded", "networkidle0"] }), | |
loginButtonHandle[0].click() //ログインボタンを押す | |
]); | |
console.log('Loyolaログイン完了'); | |
} catch (e) { | |
console.log(e); | |
return false; | |
} | |
return page; | |
}; | |
const access_entry_form = async (page) => { | |
try { | |
const curriculum_menu_handle = await page.$x(loyola_xpath.button_of_curriculum_menu); | |
await Promise.all([ | |
page.waitForXPath(loyola_xpath.button_of_curriculum_menu), | |
// page.waitForTimeout(3000), | |
curriculum_menu_handle[0].click() //「カリキュラム」のメニューを開く | |
]); | |
await page.waitForTimeout(2000); | |
const header_handle = await page.$x('//*[@id="tabmenu-li1"]/span'); | |
await Promise.all([ | |
page.waitForXPath('//*[@id="tabmenu-sub-ul1"]/li[1]/span'), | |
// page.waitForTimeout(3000), | |
header_handle[0].click() //ヘッダの「履修登録」を開く | |
]); | |
await page.waitForTimeout(2000); | |
const link_to_entry_page_handle = await page.$x('//*[@id="tabmenu-sub-ul1"]/li[1]/span'); | |
await Promise.all([ | |
page.waitForFrame(async (frame) => frame.url().includes('scs.cl.sophia.ac.jp')), | |
link_to_entry_page_handle[0].click() //ヘッダから履修登録エントリーページを開く | |
]); | |
await page.waitForTimeout(2000); | |
console.log('抽選科目エントリーページへのアクセス:成功'); | |
} catch (e) { | |
console.log(e); | |
return false; | |
} | |
return page; | |
}; | |
const continue_clicking = async (page) => { | |
try { | |
const [, iframe] = await page.frames(); //現在のページが[0]に入っている(n>0なるn個目のiframeは[n]に入る) | |
const expand_loggedin_time = async () => { | |
const eh = await page.$x(loyola_xpath.time_extension_clock); | |
await eh[0].click(); | |
}; | |
page.on("popup", expand_loggedin_time); | |
const mokusan_eh = await iframe.$x('/html/body/table[2]/tbody/tr[2]/td/table/tbody/tr[6]/td[4]'); | |
await Promise.all([ | |
iframe.waitForNavigation({ waitUntil: ["domcontentloaded", "networkidle0"] }), | |
mokusan_eh[0].click() //時間割表の水曜4限をクリック | |
]); | |
const input_eh = await iframe.$x('//*[@id="jikanwariCode"]'); | |
await input_eh[0].type('LAW62200', { delay: 120 }); //科目コード入力 | |
let cnt = 0; | |
for (; ;) { | |
const submit01_eh = await iframe.$x('//*[@id="rishuReferUpdateForm"]/p[2]/input[1]'); | |
await Promise.all([ | |
iframe.waitForNavigation({ waitUntil: ["domcontentloaded", "networkidle0"] }), | |
submit01_eh[0].click() //「登録」をクリック | |
]); | |
await sleep(randomWait(2000, 0.5, 1.1)); | |
const submit02_eh = await iframe.$x('/html/body/p[3]/input[1]'); | |
await Promise.all([ | |
iframe.waitForNavigation({ waitUntil: ["domcontentloaded", "networkidle0"] }), | |
submit02_eh[0].click() //「OK」をクリック | |
]); | |
await sleep(randomWait(2000, 0.5, 1.1)); | |
const error_eh = await iframe.$x('//span[@class="error"]'); | |
if (await error_eh.length === 0) { | |
console.log(`登録成功: ${new Date().toLocaleString()}`); | |
break; | |
} else { | |
cnt++; | |
console.log(`登録失敗: ${cnt}回目`); | |
} | |
} | |
} catch (e) { | |
console.log(e); | |
} | |
return page; | |
}; | |
(async () => { | |
const browser = await puppeteer.launch({ | |
defaultViewport: { width: 1000, height: 1000 }, | |
// args: [ | |
// '--disable-gpu', | |
// '--disable-dev-shm-usage', | |
// '--disable-setuid-sandbox', | |
// '--no-first-run', | |
// '--no-sandbox', | |
// '--no-zygote', | |
// '--single-process' | |
// ], | |
// headless: true, | |
headless: false, | |
// devtools: true, | |
timeout: 2 * 60 * 1000, | |
slowMo: 25 | |
}); | |
try { | |
const page = await browser.newPage(); | |
await page.evaluateOnNewDocument(() => { //webdriver.navigatorを消して自動操縦であることを隠す | |
Object.defineProperty(navigator, 'webdriver', ()=>{}); | |
delete navigator.__proto__.webdriver; | |
}); | |
await continue_clicking(await access_entry_form(await login(page))); | |
} catch (e) { | |
console.log(e); | |
} finally { | |
await browser.close(); | |
} | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"dotenv": "^16.3.1", | |
"puppeteer": "^21.3.4" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment