.env에 보안이 필요한 정보를 입력하고 보관하면 다른 코드가 유출되어도 보안유지 가능
npm i dotenv
EMAIL=[email address]
PASSWORD=[password]
...
//index.js
const dotenv = require('dotenv');
dotenv.config();
process.env.EMAIL;
process.env.PASSWORD
networkidle0
과 networkidle2
를 사용해봤는데 사실 차이를 아직 잘 모르겠다
Puppeteer has "networkIdle0" (0 network connections for 500ms) and "networkIdle2" (no more than 2 network connections for 500ms).
<출처> https://news.ycombinator.com/item?id=16461979
<출처> 5번째 댓글
await page.goto('https://www.~', {
waitUntil: 'networkidle0'
})
페이지 전체가 로딩되는 것이 아니면 사용하면 안된다
await page.waitForNavigation({
waitUntil: 'networkidle2,
})
networkidle2
를 사용해야한다원하는 버튼을 클릭하기 위해서 제로초는 두 단계를 사용한다.
await page.waitForSelector('selector');
await page.click('selector');
DOM selector가 충분히 로딩되기를 기다리는 것인데 이번 로그인의 경우는 없어도 잘 되는 것을 확인했다.
selector를 필수태그만 남겨 최소화하는 과정을 뜻한다
🚨 복사한 Selector는 정확하게 한 곳을 가리키지만 불필요하게 긴 경우가 많으므로 최적화해주는 것이 좋다
// Copy한 selector
$('#notion-app > div > div:nth-child(1) > main > section > div > div > div > div.notion-login > div:nth-child(3) > div.notion-focusable > input[type=email]')
// 최적화한 selector
$('input[type=email]')
// Copy한 selector
$('#notion-app > div > div:nth-child(1) > main > section > div > div > div > div.notion-login > div:nth-child(3) > div:nth-child(6)')
// 최적화한 selector
$('.notion-login div:nth-child(6)')
selector에 글자 하나씩 입력하는 방식으로 덜 로봇같다
await page.type('selector', process.env.EMAIL);
selector에 값을 바로 입력해버리는 방식
await page.evaluate((email) => {
document.querySelector('selector').value = email;
}, process.env.EMAIL);
// await page.evaluate((변수) => {
// ...
// }, 변수에 넘겨줄 값)
type처럼 타자를 치는 모션 없이 값이 한번에 입력된다.
이번 노션 로그인에서는 아래와 같은 에러가 떴고 type으로 입력시 해결되었다
Failed to load resource: ther server Failed to load resource: the server responded with a status of 404 () cs.moz.com/id?
Http Request Error: Invalid email address
const fs = require('fs');
const puppeteer = require('puppeteer');
const axios = require('axios');
const stringify = require('csv-stringify/lib/sync');
const dotenv = require('dotenv');
dotenv.config();
const crawler = async () => {
try{
const browser = await puppeteer.launch({
headless: false,
}); //브라우저 띄우기
const page = await browser.newPage(); //페이지 띄우기
await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36');
await page.goto('https://www.notion.so/42-1fb86e5e2cb7475d96cbb7f693d50dd7', {
waitUntil: 'networkidle0'
})
// notion logo click
await page.waitForSelector('.notion-topbar div:nth-child(6)');
await page.click('.notion-topbar div:nth-child(6)');
// type email
await page.waitForSelector('input[type=email]');
await page.type('input[type=email]', process.env.EMAIL);
// click "Continue with email"
await page.waitForSelector('.notion-login div:nth-child(4)');
await page.click('.notion-login div:nth-child(4)');
// type password
await page.waitForSelector('input[type=password]');
await page.type('input[type=password]', process.env.PASSWORD);
// click "Continue with password"
await page.waitForSelector('.notion-login div:nth-child(6)');
await page.click('.notion-login div:nth-child(6)');
// await page.close(); //페이지 닫기
// await browser.close(); //브라우저 닫기
} catch (e) {
console.error(e);
}
}
crawler();