2019-11-6 TIL

오늘의 배운점

  • 크롤러 최소기능만 완성했다. 처음에는 정해진 아이디로 하다가 막상 완성을 시키니 다양한 경우의 수들이 발생을 했다. 구독 여부, 구독이 아예 없을때, recovery page 등등. 하나둘씩 완성을 하면서 우선 셀레니움에서는 동작을 한다. 이제 controller로 붙여야지.
const getSubscriptionList = async () => {
  try {
    const driver = await getLogin();
    await driver.wait(until.elementLocated(By.className('zQTmif SSPGKf I3xX3c')), 10000).then(() => console.log(`class 로드되었습니다.`));
    const userSubscription = [];
    const hasSubscription = await checkHasSubscription(driver);
    console.log(`checkHasSubscription result ${JSON.stringify(hasSubscription)}`);
    if (!hasSubscription) {
      driver.quit();
      return userSubscription;
    }
    await driver.wait(until.elementLocated(By.css('#fcxH9b > div.WpDbMd > c-wiz > div > c-wiz > table > tbody')), 10000).then(() => console.log('render'));
    const list = await driver.findElement(By.css('#fcxH9b > div.WpDbMd > c-wiz > div > c-wiz > table > tbody')).then((el) => el.findElements(By.className('bzdI0b')));
    console.log(`구독서비스가 있다`);
    await list.map((element) => userSubscription.push(serviceParsing(element)));
    console.log(userSubscription);
    return userSubscription;
  } catch (e) {
    console.log(`getSubscriptionList error : ${e}`);
  }
};

const serviceParsing = async (element) => {
  const result = {};
  const list = await element.findElement(By.className('pTS2If')).findElement(By.css('a')).findElements(By.css('span'));
  result.name = await list[0].getText();
  result.plan = await list[1].getText();
  const priceField = await element.findElement(By.className('EQjZle kSHPSd')).getText();
  result.price = convertPriceReg(priceField);
  result.renewal = convertDateReg(await element.findElement(By.className('l7Glx M7PYhd')).getText());
  result.freeEndDate = convertEndDateReg(priceField);
  result.image = await element.findElement(By.className('T75of wRBX5e')).getAttribute('src');
  console.log(JSON.stringify(result));
  return result;
};
  • 처음에는 동작을 안하는줄 알았던 driver.wait(until.elementLocated(By …)) 기능을 많이 쓴다. 이 기능의 경우 지정한 element가 렌더링될때까지 기다린다. 코드가 순차적으로 실행이 되고 webdriver에서 실행이 되다보니 element가 렌더링이 전에 동작이 되서 에러가 발생하는 경우가 많았다. 생각보다 매우 유용하게 사용을 하고 있다.
// WebElement
element.findElement(By.className('pTS2If')).findElement(By.css('a')).findElements(By.css('span'));

// HTML
<div class="pTS2If">
  <a href="/store/apps/details?id=com.avast.android.vpn">
    <span>Avast VPN SecureLine: 빠른 속도 &amp; 익명 보장하는 온라인 보안</span> (
    <span>1개월</span>)
  </a>
</div>
  • 위의 코드에서 많이 배웠다. findElement(By.className(‘pTS2If’))에서는 이미 위의 HTML가장 바깥에 있는 엘리먼트들이 선택이 된거다. 나의 경우 저기서 하위 span태그들의 엘리먼트가 필요했다. By.tagName 메서드가 deprecated가 되었기때문에 css를 선택해야됬는데 selector의 개념을 잘몰랐다.
  • 상대개념이였기때문에 이미 선택한 element에서 하위에 있는 a태그를 선택하고 또 그 하위에 있는 span태그들을 findElements로 선택을 하니 원하는 값을 얻을 수 있었다.
Written on November 6, 2019