const frameHandle = await page.$("iframe");
const frame = await frameHandle.contentFrame();
const input = await frame.$eval("input[name=input2]", ele => ele.value);
데이터를 자동으로 수집하거나 입력 또는 클릭 등의 수행을 하기 위해서 주로 puppeteer를 사용합니다. 기존 글에서 puppeteer에 대해서 다룬 글들이 있으니 참고하셔도 좋습니다.
2022.10.03 - [개발 창고/NodeJS] - [Puppeteer] Element Exists
2022.09.26 - [개발 창고/NodeJS] - [Puppeteer] 현재 페이지 URL 가져오기
오늘은 동일 페이지 내에서 발생하는 iframe 내에서의 오류에 대해 이야기해볼까 합니다.
일반적으로 데이터는 $eval을 통하여 가져올 수 있습니다.
(물론 evaluate나 다른 함수들을 통하여도 가능하지만 오늘은 데이터 추출을 위한 예시로 $eval을 사용할 예정입니다.)
아래와 같이 동일 페이지 내에 두개의 html을 두고 테스트해보도록 하겠습니다.
(root) ┣ iframe.js ┣ iframe01.html ┗ iframe02.html |
현재 작업 파일은 iframe.js이고, 읽어들이려는 파일은 iframe01.html입니다. 그리고 iframe02.html은 iframe02.html에 포함된 iframe에서 호출한 파일입니다.
<!-- iframe01.html -->
<html>
<body>
<input type="text" name="input1" value="Hello"/>
<iframe src="./iframe02.html"></iframe>
</body>
</html>
<!-- iframe02.html -->
<html>
<body>
<input type="text" name="input2" value="World"/>
</body>
</html>
페이지에는 별도의 CSS 작업을 하지 않았으므로 iframe01.html을 들어가 보면 아래와 같이 보여질 겁니다.
Hello가 들어있는 input1은 일반 페이지의 input이고, World가 들어있는 input2는 네모난 박스 영역이 iframe으로 된 부분입니다. (이 부분은 css로 충분히 감춰지는 부분이므로 소스에서 확인하여 iframe내에 있는지 파악하는 것이 적합합니다.)
이때 일반적으로 input 값을 가져오기 위해서는 아래와 같이 수행하면 됩니다.
const input = await page.$eval("input[name=input1]", ele => ele.value); |
하지만 "World"가 들어있는 input2의 경우 동일하게 호출하면 아래와 같은 오류가 발생합니다.
※ 만약 해당 오류가 발생하지 않는다면 iframe이 아닌 페이지 내 어느 곳엔가 동일한 selector가 존재할 수 있습니다.
이 경우에는 browser에서 파생된 page에서 찾을 수 없고, page에서 파생된 frame에서 찾아야 합니다.
const frameHandle = await page.$("iframe"); const frame = await frameHandle.contentFrame(); const input = await frame.$eval("input[name=input2]", ele => ele.value); |
1/ page에서 해당 iframe selector를 갖는 frame Handler 조회
※ 현재는 iframe이 한 개 이기 때문에 selector로 iframe만 사용했지만, 상황에 따라 iframe id 또는 name을 지정해주어야 합니다.
2/ 조회한 frameHandle에서 HTMLIFrameElement를 조회
3/ 해당 HTMLIFrameElement에서 해당 input2를 조회
테스트를 위해 작성한 전체 iframe.js파일 내용은 아래와 같습니다.
const puppeteer = require("puppeteer"); // Crawling을 테스트를 위한 API
const path = require("path"); // 로컬 경로에 있는 iframe01.html 접근하기 위해 사용된 path API
(async() => {
const browser = await puppeteer.launch({ headless:false }); // 브라우저 생성
const page = await browser.newPage(); // 브라우저 내 신규 페이지 생성
// Step. Test페이지로 이동 (동일 파일 내 iframe01.html로 이동)
const html = path.resolve(__dirname, "iframe01.html");
await page.goto(html);
// Step. 일반적인 방법의 input value값 추출
console.log("############### INPUT 1. 기본 input value 호출 ###############")
try{
const input = await page.$eval("input[name=input1]", ele => ele.value);
console.log(input);
}catch(e){
console.log(e);
}
// Step. iframe 내 input value값 추출 (오류)
console.log("############### INPUT 2. iframe 내 input value 호출 (오류) ###############")
try{
const input = await page.$eval("input[name=input2]", ele => ele.value);
console.log(input);
}catch(e){
console.log(e);
}
// Step. iframe 내 input value값 추출 (정상)
console.log("############### INPUT 2. iframe 내 input value 호출 (정상) ###############")
try{
const frameHandle = await page.$("iframe");
const frame = await frameHandle.contentFrame();
const input = await frame.$eval("input[name=input2]", ele => ele.value);
console.log(input);
}catch(e){
console.log(e);
}
})();
'개발 창고 > NodeJS' 카테고리의 다른 글
[FS] 파일 복사 (0) | 2023.02.20 |
---|---|
[React] map에서 숫자 FOR문 사용하기 (0) | 2023.02.13 |
[알고리즘] 이진트리 (B-Tree) (0) | 2023.01.25 |
[VanillaJS] 변수 JSON 변환 가능 여부 체크 (0) | 2023.01.18 |
[ExcelJS] 내용 덮어 씌우기 (0) | 2023.01.16 |