이전 글 웹 크롤링 마우스 조작하기에 대해서
태그를 도저히 못 찾겠다면 마우스를 조작하여
직접 마우스 클릭하는 방법을 구현해서 웹크롤링을 합니다
하지만 마우스 조작하는 방법은 대도록이면 안 사용하는 것이 좋겠지요?
더 상세한 정보가 궁금하시다면 아래의 링크를 클릭해주세요
2022.09.01 - [IT_Web/Nodejs] - 웹 크롤링 마우스 조작해서 클릭하기 태그를 도저히 못 찾겠다면!?
프록시 란 컴퓨터 네트워크에서 다른 서버 상의 자원을 찾는
클라이언트로부터 요청을 받아 중계하는 서버를 말합니다
사용자의 입장에서는 자신의 웹 서핑 기록을 익명 화하기 위해 웹 프록시를 사용하기도 합니다
이러한 프록시 서버를 이용하여 우리의 IP를 다른 새로운 IP로 변경을 하여 웹크롤링을 시도합니다
그렇게 되면 익명의 유저로 또 다시 접근이 가능하게 됩니다
웹 프록시에서 새로운 IP 크롤링하여 웹 페이지 접속하기
setNewProxy 함수를 활용해서 다른 IP를 받는 작업을 합니다
먼저 나의 IP가 어떤 값으로 설정되어있는지
Daum 홈페이지 검색창 input에 value값을 할당하여
변경해가는 IP주소가 변경되는 과정을 볼 수 있을 것입니다
const puppeteer = require('puppeteer');
const writekeyboardList = require('./writekeyboardList');
const dotenv = require('dotenv'); // npm i dotenv
dotenv.config();
const setCrawler = async (production, isMouse = false) => {
let browser = await puppeteer.launch({
headless: false,
args:['--window-size=1920,1080']
});
let page = await browser.newPage();
await page.setViewport({
width: 1080,
height:1080,
})
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]
}
});
});
const fristProxies = newProxies.filter((v) => v.type === 'HTTP' && v.anonymity === 'HIA').sort((p, c) => p.latency - c.latency)[0]
await page.close();
await browser.close();
browser = await puppeteer.launch({
headless: false,
args:['--window-size=1920,1080', '--disable-notifications', `--proxy-server=${fristProxies.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(),
]);
}
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 page.keyboard.down(ShiftLeft);
await setTime(selector, 500)
await page.keyboard.press(code);
await setTime(selector,500)
await page.keyboard.up(ShiftLeft);
} else {
await page.keyboard.press(code);
}
await setTime(selector,500)
}
}
} else {
await page.keyboard.press(id);
}
}
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) => {
const setTime = await page.evaluate(async(waitTime) => {
const 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)
console.log(`waitTime[${selector}]: `, setTime)
return setTime
}
await page.goto('https://www.daum.net/');
await page.waitForSelector('.tf_keyword')
await inputValue('.tf_keyword', '내아이피'),
await Promise.all([
buttonClick(['.ico_pctop.btn_search']) ,
page.waitForNavigation(),
]);
await page.goto('http://spys.one/free-proxy-list/KR/');
return { buttonClick, inputValue, handleWriteKeyboard, setTime, setNewProxy, page, browser }
}
const crawler = async () => {
try {
const { 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 setNewProxy('https://www.daum.net/')
// await page.close();
// await browser.close();
} catch (e) {
console.log(e);
}
}
crawler()
위의 코드가 상당히 길어서 조금 부담될 수 있지만
이전 포스팅에서 알아보았던 것들을 재사용한 것이니
궁금하시면 이전 포스팅이나 카테고리를 클릭하시길 바랍니다
아래의 코드는 실질적인 크롤링 실행문이 있습니다
단지 setCrawler()가 실행되어 매서드 및 화면 노출을 하는 초기 세팅값을 설정합니다
Daum 홈페이지에서 검색창에 내 아이피를 인자 값으로 넣어
value를 할당하고
검색 버튼을 클릭해서 검색을 하여 IP주소를 확인합니다
그리고 setNewProxy()를 호출해서 다른 IP주소를 할당합니다
그럼 아래에서 setNewProxy함수에 대해 알아보도록 하겠습니다
우선 코딩 분석 전에 페이지의 형태를 확인해 봅시다
IP주소 그리고 proxy type, Anonymity, Latency가 보입니다
Proxy address는 IP주소이며,
Proxy type는 우리가 흔히 알고 있는 http 관련 사항입니다
Anonymity는 ANM, HIA, NOA 등이 있으며 이것은 익명성을 보장하는 정도라고 생각하시면 됩니다
HIA가 제일 높은 수치로 익명성을 보장받을 수 있습니다
Latency는 속도를 의미하며 수치가 낮을수록 빠르다고 할 수 있습니다
그럼 4가지의 값들을 가져오기 위해 웹크롤링을 진행합니다
4가지 타입의 태그에 접근하여 innerText 값을 가져옵니다
그것을 배열로 만들어서 newProxies 변수에 담아서 filter함수를 적용해서 제일 빠른 IP주소를 가져옵니다
가져온 IP주소를 변수에 담으면 기존 페이지와 브라우저를 닫고
새 브라우저와 새 페이지를 프록시 서버 설정하여 활성화합니다
이때 Daum 홈페이지에 다시 한번 내 아이피를 확인하면
변경된 IP주소를 확인할 수 있습니다
그리고 페이지 중간중간 이동할 경우 waitForSelector()을 사용해서 새로운 페이지의 지정된 태그를 기다리게 됩니다
그리고 buttonClick함수가 실행되고 페이지가 이동된다면
Promise.all()을 사용하여 순차적으로 넣어 줍니다
* inputValue, buttonClick 함수의 설명은 이전 포스팅을 참고하세요
이렇게 설정하면 프록시 IP주소를 가져올 수 있습니다
한번 직접 코딩을 해서 웹크롤링을 돌려보는 것이 더욱 이해가 빠르다고 생각합니다
그럼 오늘도 이렇게 공부를 하였습니다
IT 개발이란 것은 영원히 공부를 해야 하지 않을까? 합니다
새로운 언어들이 나오고 웹의 새로운 환경들을 나오면서
더욱 우리는 공부를 해야 할 듯합니다
아직 IT 대모험이 끝나지 않았으니까
앞으로도 힘내시길 바랍니다
그럼 다음 포스팅도 기대해주세요
'IT_Web > Nodejs' 카테고리의 다른 글
웹 크롤링 puppeteer 파일 업로드 및 로그인 유지 설정하기 (0) | 2022.09.06 |
---|---|
웹 크롤링 puppeteer로 mysql 및 sequelize 활용하여 DB연동하기 (0) | 2022.09.03 |
웹 크롤링 마우스 조작해서 클릭하기 태그를 도저히 못찾겠다면!? (0) | 2022.09.01 |
웹 크롤링 puppeteer로 alert, prompt, confirm 창 얼럿창 제어 및 컨트롤 하기 (0) | 2022.08.31 |
웹 크롤링 puppeteer 활용 및 keyboard press 함수로 키보드 코드 입력하기 (0) | 2022.08.30 |