굿스플로 카카오 알림톡 API 작업 중

기존에 워드프레스용으로 개발했던 플러그인을 일반 PHP 프로그램에서 사용하기 위해서 코드 변경 작업을 진행 중이다. 워드프레스 플러그인에서 불필요한 코드들을 제거하고 적용한 프로그램에 맞게 코드를 바꾸고 있는데.. 알림톡 API 작업은 항상 템플릿 검수 때문에 일정에 차질이 생긴다. 검수를 통과해야 테스트든 뭐든 할 수 있는데.. 검수 결과를 다시 한번 체크해봐야겠다. 오늘까지는 끝내고 싶은데.. 내게 기회를 줄까?

[nodejs] puppeteer 를 이용한 네이버 회원 로그인

puppeteer 는 nodejs기반 헤드리스 브라우저 컨트롤 API 이다. puppeteer 를 이용하여 네이버 회원 로그인 후 네이버 메인 스크린샷을 출력하는 코드이다.

puppeteer 설치

npm install --save puppeteer

Ubuntu 16.04 환경에서 아래 스크립트 실행 때 error while loading shared libraries: libXss.so.1  또는 error while loading shared libraries: libgconf-2.so.4 오류가 발생하면 아래 패키지를 설치해준다.

sudo apt-get install libxss1 libgconf

스크린샷에서 한글이 제대로 표시되지 않는다면 한글폰트 관련 패키지를 설치한다.

sudo apt-get install libfontenc1 libxfont1 xfonts-encodings xfonts-utils xfonts-base xfonts-75dpi
sudo apt-get install language-pack-ko
sudo apt-get install fonts-nanum fonts-nanum-coding fonts-nanum-extra
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  const naver_id = "네이버 아이디";
  const naver_pw = "네이버 비밀번호";

  await page.goto('https://nid.naver.com/nidlogin.login');

  await page.evaluate((id, pw) => {
    document.querySelector('#id').value = id;
    document.querySelector('#pw').value = pw;
  }, naver_id, naver_pw);

  await page.click('.btn_global');
  await page.waitForNavigation();

  await page.goto('https://naver.com');

  await page.screenshot({ path: 'naver.png', fullPage:true });

  await browser.close();
})();

위 코드 중 naver_id 와 naver_pw 를 네이버 회원정보로 설정한 후 스크립트를 실행하면 아래와 같은 스크린샷을 얻을 수 있다. Read More

[nodejs] request, cheerio 를 이용한 웹페이지 크롤링

nodejs 를 이용하 웹페이지를 크롤링하는 것을 스터디 하고 있다. 아래는 nodejs의 request, cheerio 모듈을 이용하여 SIR 의 자유게시판의 제목, 작성자이름, ip 정보를 크롤링하는 코드이다. 자유게시판 리스트에 접속하여 게시글보기 링크의 href 값을 얻어 각 게시글보기 페이지에 접속하여 제목, 작성자명, ip 정보를 수집한다. SIR 사이트에 동시접속하는 것을 막기 위해 async, await 구문을 사용하여 순차적으로 게시글 보기가 실행되도록 했다.

사용모듈

const request = require('request').defaults({jar: true});
const cheerio = require('cheerio');

function downloadPage(url)
{
    return new Promise((resolve, reject) => {
        request(url, (error, response, body) => {
            if (error) reject(error);
            if (response.statusCode != 200) {
                reject('Invalid status code <' + response.statusCode + '>');
            }
            resolve(body);
        });
    });
}

function sleep(ms){
    return new Promise(resolve => {
        setTimeout(resolve, ms)
    });
}

async function getInfo(urls)
{
    try {
        for (i=0; i<urls.length; i++) {
            if (i > 0)
                await sleep(5000);

            var url = urls[i];
            var patt = /^https?:/;
            if (!patt.test(url))
                url = "https:" + url;
            var body = await downloadPage(url);

            var $ = cheerio.load(body);

            var title = $("#head_title", $("header.vbo_head")).text().trim();
            var name  = $("span.member", $("ul#head_info")).text().trim();
            var ip    = $("#info_name", $("ul#head_info")).children().remove().end().text().trim();

            console.log(title + " => " + name + " " + ip);
        }
    } catch (error) {
        console.log(error);
    }
}

try {
    request("https://sir.kr/cm_free", (error, response, body) => {
        var $ = cheerio.load(body);
        var hrefs = [];

        var lists = $("a.title_link", ".li_title", $("#sir_lbo"));

        lists.each(function() {
            var href = $(this).attr("href");

            hrefs.push(href);
        });

        if (hrefs.length > 0) {
            getInfo(hrefs);
        }
    });
} catch (error) {
    console.log(error);
}

각 게시글보기 실행은 await sleep(5000);  코드를 통해 5초 간격으로 실행되도록 했다.

[쉘스크립트] 텍스트파일의 라인을 읽어 ip와 id 구분하기

텍스트 파일의 각 라인을 읽어 해당 라인에서 ip 와 id 를 구분해서 출력하는 코드이다. 텍스트의 파일은 아래와 같은 형식이다. ip 와 이름-id 는 탭으로 구분된 상태이다.

192.168.10.100	홍길동-gildong
192.168.10.101	김철수-kcs0297

쉘스크립트 코드는 아래와 같다.

#!/bin/bash
IPS=()
IDS=()

i=0

while IFS='' read -r line || [[ -n "$line" ]]; do
    IFS=$'\t'
	tmp=($line)
	IPS[${i}]=${tmp[0]}

	str=${tmp[1]}

	IFS=$'-'
	tmp=($str)
	IDS[${i}]=${tmp[1]}

	i=${i}+1
done < "$1"

for (( i=0; i<${#IPS[@]}; i++)); do
	echo "${IPS[i]} / ${IDS[i]}"
done

쉘스크립트 실행 방법을 ./read.sh hosts 와 같다. 쉘스크립트 파일과 텍스트 파일을 지정해주면 된다. 실행 결과는 아래와 같다.

192.168.10.100 / gildong
192.168.10.101 / kcs0297

참고
– https://stackoverflow.com/questions/1951506/add-a-new-element-to-an-array-without-specifying-the-index-in-bash
– https://unix.stackexchange.com/questions/410710/splitting-a-line-into-array-in-bash-with-tab-as-delimiter
– https://stackoverflow.com/questions/27291158/split-tab-separated-string-into-array-in-bash
– https://stackoverflow.com/questions/6654849/how-to-split-a-string-in-bash-delimited-by-tab