프로그래밍/JS, Node.js

[Node.js] Selenium 사용법을 익혀보자

Lou Park 2021. 1. 3. 23:49

Selenium은 웹 드라이버를 통해 웹 브라우저를 자동화하여 웹 테스트를 도와주는 툴이다. 말은 착하지만 매크로를 만들거나 크롤링 할때도 도움이 된다. ^^ 실제 브라우저를 띄우고 코드를 수행할 수 있으며, 일반적으로 크롤링 하는 방식보다 훨씬 더 상호작용을 사람같이! 할 수 있다. 페이지가 다 뜰때까지 기다리고, 클릭하고, 입력하는 등...

그러면 Node.js 에서 selenium을 사용하는 방법을 익혀보자.

 

패키지 설치

먼저 selenium-webdriver 패키지를 설치해야한다.

npm i selenium-webdriver

파이어 폭스 브라우저로 Selenium을 실행해야 할 경우, geckodriver를 설치해야한다.

npm i geckodriver

실행환경이 Ubuntu일 경우 geckodriver 설치는 다음과 같이한다.

wget https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-linux32.tar.gz
tar -xvzf geckodriver-v0.24.0-linux32.tar.gz
chmod +x geckodriver

 

코드 작성

세팅이 끝났으니, selenium으로 네이버를 실행하고 종료하는 코드를 작성 해 보겠다. (app.js)

const {Builder, By, Key, until} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder()
.forBrowser('firefox')
.build();
try {
// 네이버 실행
await driver.get('https://www.naver.com/');
}
finally{
driver.quit();
}
})();

node app.js 를 실행해보면 Firefox 브라우저가 열리고, 네이버에 접속 후 창이 꺼질 것이다.

그럼 유용한 메소드 전부를 활용해서 네이버 검색어 결과를 추리는 코드를 작성 해 보겠다.
세부 사항은 주석을 참조하면된다.

  • Input에 텍스트 입력하기
  • 요소 클릭하기
  • Loop를 돌며 Element 내용 읽기
const {Builder, By, Key, until} = require('selenium-webdriver');
(async function example() {
let driver = await new Builder()
.forBrowser('firefox')
.build();
try {
// 네이버 실행
await driver.get('https://www.naver.com/');
// Javascript를 실행하여 UserAgent를 확인한다.
let userAgent = await driver.executeScript("return navigator.userAgent;")
console.log('[UserAgent]', userAgent);
// 네이버 검색창의 id는 query이다. By.id로 #query Element를 얻어온다.
let searchInput = await driver.findElement(By.id('query'));
// 검색창에 '회 숙성하는 법'을 치고 엔터키를 누른다.
let keyword = '회 숙성하는 법'
searchInput.sendKeys(keyword, Key.ENTER);
// css selector로 가져온 element가 위치할때까지 최대 10초간 기다린다.
await driver.wait(until.elementLocated(By.css('#header_wrap')), 10000);
// total_tit라는 클래스 명을 가진 element들을 받아온다.
let resultElements = await driver.findElements(By.className('total_tit'));
console.log('[resultElements.length]', resultElements.length)
// 검색 결과의 text를 가져와서 콘솔에 출력한다.
console.log('== Search results ==')
for (var i = 0; i < resultElements.length; i++) {
console.log('- ' + await resultElements[i].getText())
}
// 검색결과의 첫번째 링크를 클릭한다.
if (resultElements.length > 0) {
await resultElements[0].click();
}
// 4초를 기다린다.
try {
await driver.wait(() => { return false; }, 4000);
} catch (err) {
}
}
finally{
// 종료한다.
driver.quit();
}
})();

크롤링에 자주 쓰이는 메소드들은 거의 나온것 같다! 이 코드를 실행시키면, 네이버에 회 숙성하는 법을 검색하고 제일 첫번째 글을 클릭한뒤, 종료하게 된다. 실행시 로그는 다음과 같다.

[UserAgent] Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:83.0) Gecko/20100101 Firefox/83.0
[resultElements.length] 11
== Search results ==
- 입질의 추억 :: 생선회를 숙성하는 방법(숙성회를 먹는 이유) - 입질의 추억
- 다시마 숙성회, 광어 곤부지메 만드는 방법
- 참돔 숙성회 만드는 방법
- 생선회 맛있게 먹는법!! Part.4 숙성회가 맛있는 이유
- 사가정 맛집 도미회가 맛있는슌락 맛있는 참돔 마쓰가와 숙성법
- 참치회 인터넷 주문 배송 :: 참치 해동/숙성 하는 법. 참치몰 후기
- 노량진수산시장 모듬회, 숙성회, 방어회 싸게먹는법
- 연남동 맛집, 경양마구로! 숙성시킨 참치회로 만든 회덮밥! 최고! (+ 맛있게 먹는 )
- 연안부두1월제철수산물 10키로이상 특대방어 가격 시세 숙성대방어회먹는법 장군씨푸드
- 연어 숙성 하는법::생연어 곤부지메해서 회 떠먹기
- 이렇게 맛있는 12월의 수산물이라니! 과메기부터 굴, 방어까지 겨울 수산물 레시피

실제 검색결과 이미지

 

For Non-gui systems

GUI가 없는 Ubuntu등 서버OS에서 이 코드를 실행하려고하면, (내 기억이 맞다면) 아래와 같은 오류가 날 것이다. 이때는 headless 모드로 selenium을 실행시켜 주어야한다. headless로 설정하게 되면 실제 브라우저가 보이지 않는다.

selenium.common.exceptions.WebDriverException: Message: invalid argument: can't kill an exited process

Firefox Options에서 headless 모드를 설정할 수 있다. options에는 이 외에도 다른 유용한 설정을 할 수 있다. 아래는 몇가지 예시다.

const {Builder, By, Key, until} = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
(async function example() {
let driver = await new Builder()
.forBrowser('firefox')
.setFirefoxOptions(
new firefox.Options()
// headless 모드 사용
.headless()
// 창 크기 설정
.windowSize({
width: 640,
height: 480
})
// custom user agent 설정하기
.setPreference("general.useragent.override", "custom-user-agent")
)
.build();
try {
// ... your code
}
finally{
driver.quit();
}
})();

 

맺으며

오늘 Selenium을 가지고 놀면서 Cloudflare로 보호되는 웹을 뚫어보려고 삽질을 했는데 결국 실패해서 그냥 저냥 알게된 사용법을 블로그에 올려봤다. ㅠㅠ 그래도 실제 브라우저로 딱딱딱 집어주는 코드를 작성할 수 있다니 다음에 유용한일이 생기겠지...
마지막으로 Javascript용 Selenium document 주소 뿌리고 가겠다.

https://www.selenium.dev/selenium/docs/api/javascript/index.html