이전 글에서는 웹크롤링에서 간단하게 DB 연동하기에 대해서
DB 연동으로 웹크롤링을 보다 효율적으로 사용하는 방법을 알아보았습니다
DB 연동으로 정보를 저장해서 데이터 관리는 물론 중복된 데이터까지
관리가 가능하니 웹 크롤링을 보다 능률적으로 실행할 수 있을 것입니다
더 자세히 알고 싶으시다면 아래의 링크를 클릭해주세요
2022.09.03 - [IT_Web/Nodejs] - 웹 크롤링 puppeteer로 mysql 및 sequelize 활용하여 DB 연동하기
로그인 유지 및 파일 업로드 알아보기
오늘은 puppeteer를 활용해서 파일 업로드와
로그인 정보를 유지하는 방법을 알아보려고 합니다
그럼 우선 전체 코드를 보시겠습니다
아래의 코드를 보시면 진행이 많이 되었습니다
이전 포스팅을 하나씩 참고하시면 완성하실 수 있으니 관심 있으시다면 확인해보세요
const puppeteer = require('puppeteer');
const writekeyboardList = require('./writekeyboardList');
const callElement = require('./mouseHandleHtml');
const dotenv = require('dotenv'); // npm i dotenv
const db = require('./models');
const fs = require('fs')
dotenv.config();
const setCrawler = async (production, isMouse = false) => {
await db.sequelize.sync();
let browser = await puppeteer.launch({
headless: false,
args:['--window-size=1920,1080'],
userDataDir: 'C:\Users\kimsangjin\AppData\Local\Google\Chrome\User Data'
});
let page = await browser.newPage();
await page.setViewport({
width: 1080,
height:1080,
})
if (!production && isMouse) {
await callElement(page)
}
await page.on('dialog', async (dialog) => {
console.log(`dialog`, dialog)
console.log(`type: ${dialog.type()} / message: ${dialog.message()}`)
if(dialog.type() === 'prompt') {
await dialog.accept('https://www.tistory.com/')
}
if(dialog.type() === 'alert'){
await dialog.dismiss();
}
if(dialog.type() === 'confirm'){
await dialog.accept();
}
})
const setNewProxy = async(crawlerUrl) => {
const newProxies = await page.evaluate(async() => {
const ips = Array.from(document.querySelectorAll('tr > td:first-of-type > .spy14')).map((v) => v.innerText)
const types = Array.from(document.querySelectorAll('tr > td:nth-of-type(2)')).map((v) => v.innerText)
const anonymity = Array.from(document.querySelectorAll('tr > td:nth-of-type(3)')).map((v) => v.innerText)
const latencies = Array.from(document.querySelectorAll('tr > td:nth-of-type(6) > .spy1')).map((v) => v.innerText)
return ips.map((v, i) => {
return {
ip: v,
type: types[i],
latency: latencies[i],
anonymity: anonymity[i].toString()
}
});
});
const fristProxies = newProxies.filter((v) => v.type.startsWith('HTTP')).sort((p, c) => p.latency - c.latency)
console.log('fristProxies', fristProxies)
await Promise.all(fristProxies.map(async (v) => {
return await db.Proxy.create({
ip: v.ip,
type: v.type,
latency: v.latency,
anonymity: anonymity.toString()
});
}))
await page.close();
await browser.close();
browser = await puppeteer.launch({
headless: false,
args:['--window-size=1920,1080', '--disable-notifications', `--proxy-server=${fristProxies[0].ip}`]
});
page = await browser.newPage();
await page.goto(crawlerUrl);
await page.waitForSelector('.tf_keyword')
await inputValue('.tf_keyword', '내아이피'),
await Promise.all([
buttonClick(['.ico_pctop.btn_search', 'ico_ksearch.btn_ksearch']),
page.waitForNavigation(),
]);
await setTime(4000)
await page.close();
await browser.close();
await db.sequelize.close()
}
const handleWriteKeyboard = async (selector, id) => {
const writeList = writekeyboardList()
const idOfList = [...id]
if(selector){
await page.click(selector);
console.log(`idOfList`, idOfList)
for (const id of idOfList) {
const inputValue = await writeList.filter(element => element.ShiftLeft === id || element.key === id )
if (inputValue.length > 0) {
const code = inputValue[0].code
const ShiftLeft = inputValue[0].ShiftLeft === id ? 'ShiftLeft' : ''
if (ShiftLeft) {
await setTime(selector, 0, 'key')
await page.keyboard.down(ShiftLeft);
await setTime(selector, 0, 'key')
await page.keyboard.press(code);
await setTime(selector,0, 'key')
await page.keyboard.up(ShiftLeft);
} else {
await page.keyboard.press(code);
}
await setTime(selector,0, 'key')
}
}
} else {
await page.keyboard.press(id);
}
}
const getSelectEl = async(selector) => {
const selectedEl = await page.evaluate((selector) => {
console.log('selector', selector)
const temEl = document.querySelector(selector)
console.log('selector', temEl)
return temEl
}, selector)
console.log('selector', selectedEl)
return selectedEl
}
const fileUpload = async() => {
const pathFile = 'C:\Users\kimsangjin\Desktop'
const fileExitst = await fs.existsSync(`${pathFile}/travis_1.png`)
if(fileExitst){
const input = await page.$("#m_attach_file");
await input.uploadFile(`${pathFile}/freelanceDeveloper.png`)
return true
}
return false
}
const inputValue = async (selector, value) => {
await page.evaluate((selector, value) => {
document.querySelector(selector).value = value
}, selector, value)
await setTime(selector)
}
const buttonClick = async (selector, nextSelector = '', type = '') => {
await page.evaluate((selector) => {
if (document.querySelector(selector[0])) {
document.querySelector(selector[0]).click();
} else {
document.querySelector(selector[1]).click();
}
}, selector)
if(type === 'login'){
// waitForRequest(요청 대기), waitForResponse(응답 대기)
const res = await page.waitForResponse(res => {
return res.url().includes('graphql')
})
const result = await res.json()
console.log('login', result);
if(await result.extensions.is_final){
await setTime(type, 2000)
await page.keyboard.press('Escape')
}
} else if(type === 'logOut'){
await page.waitForNavigation()
} else {
if(nextSelector){
await page.waitForSelector(nextSelector)
}
if(type === 'wait') await setTime(selector)
}
}
const setTime = async (selector = 'normal', waitTime = 0, type= '') => {
const setTime = await page.evaluate(async(waitTime, type) => {
let timeList =[]
if(type === 'key'){
timeList = await [569, 311, 257, 175, 306, 123, 428, 497, 298, 211, 379, 108, 512, 139, 249];
} else {
timeList = await [3975, 4547, 5231, 6397, 7894, 3394, 4206, 5147, 6932, 7430, 3561, 4896, 5877, 6407, 7133];
}
let randomTime = await timeList[Math.floor(Math.random() * timeList.length)]
if (waitTime > 0) randomTime = waitTime
await new Promise(r => setTimeout(r, randomTime))
return randomTime
}, waitTime, type)
console.log(`waitTime[${selector}]: `, setTime)
return setTime
}
return { fileUpload, getSelectEl, buttonClick, inputValue, handleWriteKeyboard, setTime, setNewProxy, page, browser }
}
const crawler = async () => {
try {
const { getSelectEl, buttonClick, inputValue, handleWriteKeyboard, setTime, setNewProxy, page, browser } = await setCrawler(JSON.parse(process.env.PRODUCTION));
const id = await process.env.EMAIL;
const password = await process.env.PASSWORD;
await page.goto('https://office.hiworks.com/polarium.co.kr/home#loginUrl=mail/webmail/m_list/b0');
await setTime()
const isLogin = await getSelectEl('.menu.office')
if(isLogin){
console.log('이미 로그인이 되어있습니다.')
await buttonClick(['.menu.office'], '.main-btn');
} else {
await page.waitForSelector('#office_id');
await setTime()
await handleWriteKeyboard('#office_id', id)
await setTime()
await handleWriteKeyboard('#office_passwd', password)
await setTime()
await buttonClick(['.int_jogin'], '.main-btn');
}
await page.waitForSelector('.main-btn')
await buttonClick(['.main-btn'], '#to_addr');
await page.waitForSelector('#to_addr')
await inputValue('#to_addr', '김상진');
await setTime('', 500)
await page.keyboard.press('Enter');
await page.waitForSelector('#m_attach_file')
await fileUpload()
await setTime('', 500)
await buttonClick(['.detail_select > a']);
} catch (e) {
console.log(e);
}
}
crawler()
로그인 유지 알아보기
먼저 로그인 유지 방법을 알아보도록 하겠습니다
아래의 userDateDir를 추가하면 간단하게 로그인 유지가 됩니다
하지만 크롬만 가능하니 크롬을 설치하고 아래의 경로대로 설정하시면 간단히 됩니다
아래처럼 로그인 유지가 된다면
로그인에만 있는 태그를 선택해서 있으면 로그인이 되었다는 의미로
분기를 하여 코드 작성할 수 있습니다
puppeteer 활용하여 파일 업로드 하기
이제는 어느 정도 하실 수 있다고 가정하겠습니다
그래서 여러 함수를 세팅해서 사용하고 있으니 참고하시길 바랍니다
로그인 후
fileUpload함수를 아래와 같이 실행합니다
우선 파일 위치가 필요합니다
그 위치에 현재 올리려는 파일이 있는지 존재 여부를 확인하여
있을 때만 파일 업로드를 실행합니다
이때 이름은 db에 저장된 파일을 올리도록 하는 것이 좋을 듯합니다
다음에 기회 되면 적용하도록 하고
지금은 특정 파일만 올리도록 하겠습니다
아래의 이미지를 보면 파일 첨부라는 글이 보이지만
그 밑에 input type='file'로 정의된 것을 확인할 수 있습니다
그것을 위에 처럼 input을 가져와서 .uploadFile()와 경로를 지정해서 호출하면
파일이 업로드되는 것을 확인할 수 있습니다
이때 꼭 page.$()를 활용해서 해야 한다는 점 확인하세요
이렇게 로그인 유지와 파일 업로드를 알아보았습니다
node.js에서 메일 보낼 수 있는 라이브러리가 존재합니다
그러니 그것도 활용하는 것이 좋을 듯합니다
크롤링보다는 라이브러리를 사용하는 것이 간편하겠지요
그럼 오늘도 한걸음 나아가셨길 바라며
IT대모험을 즐기며 다음 포스팅에서 찾아뵙겠습니다
그럼 파이팅 하세요!
'IT_Web > Nodejs' 카테고리의 다른 글
Node활용해서 express 서버로 HTML 노출 및 서빙하기 (0) | 2022.09.14 |
---|---|
Node에서 중요한 NPM은 무엇이며, 그 활용법을 알아보자 (2) | 2022.09.10 |
웹 크롤링 puppeteer로 mysql 및 sequelize 활용하여 DB연동하기 (0) | 2022.09.03 |
웹 크롤링 puppeteer 프록시 IP 적용하기 그런데 대체 프록시 란? 뭘까? (1) | 2022.09.02 |
웹 크롤링 마우스 조작해서 클릭하기 태그를 도저히 못찾겠다면!? (0) | 2022.09.01 |