1초에 10번씩 클릭하면 안되므로 사람인척 해야함.
userAgent
: 내 브라우저가 크롬인지, 파폭인지 나타내는 문자열 접속할 때 bot은 bot
이라고 티가남. 따라서 정상적인 브라우저로 속이기 위해서
npm i puppeteer
Chromium
브라우저를 같이 받으므로 서버용량이 1기가정도 여유가 되어야함페이지 열고, 기다리고하는 작업들은 비동기작업이라서 퍼펫티어 명령어는 앞에 await
를 붙이는 비동기 처리를 해야한다.
const crawler = async() => {
try{
const browse = await puppeteer.launch({ headless: false});
const page = await brower.newPage();
await page.goto('secho.com'); //페이지이동
await page.waitFor(3000); //로딩 후 3초뒤 종료시키기
await page.close();// 페이지 닫기
await browser.close(); // 브라우저 닫기
} catch(e){
console.error(e);
}
}
위의 예제에서 headless
옵션을 사용했다
true
: 볼 수없음false
: 볼 수있음CLI
형태로 사용하므로 배포할 때는 true
를 적용headless: process.env.NODE_ENV === 'production'
: 환경변수 사용으로 배포일 때만 적용하도록 사용을 많이함await page.goto(url);
await page2.goto(url);
await page3.goto(url);
Promise.all
을 사용해서 동시에 진행되도록 할 수 있음.const [page, page2, page3] = await Promise.all([
browser.newPage(),
browser.newPage(),
browser.newPage()
]);
await Promise.all([
await page.goto(url);
await page2.goto(url);
await page3.goto(url);
]);
await Promise.all(records.map(async (r,i) => {
const page = await browser.newPage();
await page.goto(r[1]);
const scoreEl = await page.$('.score.score_left .star_score');// $가 태그찾는 메소드
if(scoreEl){//태그를 제대로 찾았는지 확인해야함
const text = await page.evaluate(tag => tag.textContent, scoreEl); // scoreEl 태그에서 tag.textContent를 반환한다.
}
}));
크롤링을 차단하는 페이지는 page.waitFor(ms)
을 조금씩 늘려보면서 사용해보자
evaluate
: JS코드를 사용할 수 있게 해주는 함수
await page.evaluate(( { magicId, magicPw } ) => {
document.getElementById( "loginId" ).value = magicId;
document.getElementById( "loginPw" ).value = magicPw;
// document.getElementsByClassName( "btn_login" ).disabled = false;
}, { magicId, magicPw } );
npm i csv-stringify
parse의 반댓말 = stringify
const result = [];
result.push([r[0], r[1], text.trim()]);//2차원 배열 push
...
const str = stringify(result); //2차원 배열을 문자열로
fs.writeFileSync('csv/result.csv', str);//문자열을 csv파일로 쓰기
크롤링 못지않게 중요한 결과순서 맞추기
result.push([r[0], r[1], text.trim()]);
-> 배열 순서 보장 X
인덱스를 사용한다.
result[i] = [r[0], r[1], text.trim()];
evaluate 사용법
가져와야하는 정보가 많아질수록 코드가 지저분해질 수있어서 다음과 같은 방법으로 사용
하나의 evaluate
로 DOM에 접근할수있고 원하는 결과를 가져올 수 있음.
//const 태그핸들러 = await page.$(선택자);
const text = await page.evaluate(() => {
//evaluate안에서 쓸 수있는 document조작
document.querySelector('.score.score_left .star_score');
if (score){
return score.textContent;
//태그가 많아지는 경우
return {
score: score.textContent,
score2: score2.textConten;t
}
}
});
제일 중요한 것!! :smile:
봇을 검사하는 사이트를 피하기 위해 사람을 흉내내야함 이 챕터는 흉내내기 위한 방법을 소개
크롤러를 막는 기본적인 방법 userAgent
퍼펫티어말고 axios에서도 userAgent 변경해서 보내는 것도 좋음
Postman
도 userAgent에 적혀있어서 막힐수도있음
navigator.userAgent
: 내가 무슨 브라우저를 쓰는지 알려줌
page.setUserAgent('브라우저정보')
로 bot인것 속이기
순차적으로 페이지 검사
await page.setUserAgent('Mozilla/5.0....');
//사람은 동시에 검색을 못하므로 페이지 하나만 사용
const page = await browser.newPage();
for (const [i, r] of records.entries()){
await page.goto(r[1]);
//userAgent적용되었는지 검사
console.log(await page.evaluate('navigator.userAgent'));
const text = await page.evaluate(() => {
...
//DOM에서 데이터 추출
return
});
//사람 흉내 -> 3초 기다렸다가 반복
await page.waitFor(3000);
}
=> 동시성을 잃기때문에 웹서버가 차단을 하는지에 대한 테스트를 잘해보아야함
=> 클라우드로 서버 여러대를 만들어서 동시에 가져오도록 하는 방법도 있음