728x90
반응형

이전 글 웹 크롤링 마우스 조작하기에 대해서

 

태그를 도저히 못 찾겠다면 마우스를 조작하여

직접 마우스 클릭하는 방법을 구현해서 웹크롤링을 합니다

하지만 마우스 조작하는 방법은 대도록이면 안 사용하는 것이 좋겠지요?

 

더 상세한 정보가 궁금하시다면 아래의 링크를 클릭해주세요

 

 

2022.09.01 - [IT_Web/Nodejs] - 웹 크롤링 마우스 조작해서 클릭하기 태그를 도저히 못 찾겠다면!?

 

웹 크롤링 마우스 조작해서 클릭하기 태그를 도저히 못찾겠다면!?

이전 포스팅 얼럿창 컨트롤하기에 대하여 웹 크롤링 중 갑자기 얼럿창이 노출될 경우 닫지 않고서는 다음 진행이 어렵습니다 그래서 puppeteer는 이벤트 리스너와 같은 기능을 하는 함수를 가지고

tantangerine.tistory.com

 

 

프록시 란 컴퓨터 네트워크에서 다른 서버 상의 자원을 찾는

클라이언트로부터 요청을 받아 중계하는 서버를 말합니다

사용자의 입장에서는 자신의 웹 서핑 기록을 익명 화하기 위해 웹 프록시를 사용하기도 합니다

 

이러한 프록시 서버를 이용하여 우리의 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 대모험이 끝나지 않았으니까

앞으로도 힘내시길 바랍니다

 

그럼 다음 포스팅도 기대해주세요

 

 

 

 

 

 

 

728x90
반응형

+ Recent posts

Powered by Tistory, Designed by wallel