안녕하세요?
작년에 humit 님과 네모 님의 도움으로 작성했던 그누보드(아미나) 자동 글 작성 스크립트를 보완하여,
일본기상협회(tenki.jp)의 우리나라 날씨를 파파고 SMT로 번역한 후
그누보드에 자동으로 게시글을 작성하는 스크립트를 작성했습니다.
이 글을 빌어 humit 님과 네모 님께 다시 한 번 진심으로 감사드립니다! :)
우선 이 스크립트는 어디까지나 연습용임을 감안해주시고 연습 용도로만 사용해주시기를 부탁드립니다 ㅠㅠ
제가 나중에 제대로 된 사이트를 오픈하게 되면
초기에 게시판이 너무 썰렁한 경우에 저작권법을 준수하는 범위 내에서 응용해서 사용하려고 하네요 ^^
그누보드 게시글 자동작성 함수와 관련해서는 도와주세요 게시판에 제가 올렸던 글을 참조하시면 됩니다.
당시에 humit 님께서 SQL 인젝션 관련하여 보완하라고 조언해주신 부분을 수정했고
(제가 addslashes(trim())을 넣기는 했는데 humit 님께서 말씀하신대로 제대로 수정했는지는 모르겠습니다 ㅠㅠ)
아울러 특정 IP에서만 PHP 파일이 실행되도록 수정하여 조금이나마 보안성을 높였습니다.
그래도 불안하여 함부로 실행되지 않도록 파일명을 길게 작성했습니다.
<?php define('_INDEX_', true); if ($_SERVER['REMOTE_ADDR'] === '실행을 허용할 IP') { include_once('./_common.php'); include_once("./simple_html_dom.php"); // Simple HTML DOM Parser를 필요로 합니다. date_default_timezone_set("Asia/Seoul"); $url = "https://tenki.jp/world/5/89/47108/"; // tenki.jp의 우리나라 예보 URL $ch = cURL_init(); cURL_setopt($ch, CURLOPT_URL, $url); cURL_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response = cURL_exec($ch); cURL_close($ch); $html = str_get_html($response); function translation($skycondition) // 이하 파파고 SMT 번역기 함수 { $client_id = "파파고 SMT ID"; $client_secret = "파파고 SMT PW"; $encText = urlencode($skycondition); $postvars = "source=ja&target=ko&text=".$encText; $smturl = "https://openapi.naver.com/v1/language/translate"; $is_post = true; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $smturl); curl_setopt($ch, CURLOPT_POST, $is_post); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch,CURLOPT_POSTFIELDS, $postvars); $headers = array(); $headers[] = "X-Naver-Client-Id: ".$client_id; $headers[] = "X-Naver-Client-Secret: ".$client_secret; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec ($ch); $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close ($ch); preg_match('/ext...(.+)...src/', $response, $match); if ($match[1] == "세이이치 비") { // 유독 이 부분 번역이 매끄럽지 않으므로 수정해줍니다. $match[1] = "맑음 때때로 비"; } if($status_code == 200) { return $match[1]; } else { return "Error:".$response; } } $today_date = date("d"); // 이하 오늘의 날씨 $today = $html->find('table[class=world-forecast-entry-table]' ,0); $today_sky = translation($today->find('img', 0)->title); $today_tempmax = $html->find('td[class=high-temp]', 0)->plaintext; $today_tempmin = $html->find('td[class=low-temp]', 0)->plaintext; $contents = "<strong style='color:blue'>".$today_date." </strong>".$today->find('img', 0)." ".$today_sky. " ".$today_tempmax." / ".$today_tempmin."<br>"; $body = $html->find('table[class=forecast-point-week]', 0); // 이하 일주일 날씨 예보 $str_body = $body; // DOM tree를 문자열로 변경합니다. preg_match_all('/([0-9]{1,2})日/', $str_body, $matches); $sky = $html->find('td[class=weather-icon]'); $tempmax = $html->find('span[class=high-temp]'); $tempmin = $html->find('span[class=low-temp]'); $number = count($sky); for ($n = 0; $n < $number; ++$n) { $skycondition_kr = translation($sky[$n]->plaintext); $contents = $contents."<strong style='color:blue'>".$matches[1][$n]." </strong>".$sky[$n]->find('img', 0)." ".$skycondition_kr." ".$tempmax[$n]->plaintext." / ".$tempmin[$n]->plaintext."<br>"; } $html->clear(); unset($html); function board_write($bo_table, $subject, $contents, $mb_id) // 이하 자동 글 작성 함수 { global $g5; $mb = get_member($mb_id); $write_table = "g5_write_{$bo_table}"; $wr_num = get_next_num($write_table); $wr_reply = ''; $ca_name = ""; $html = "html1"; $secret=""; $mail = ""; // 태그를 사용하되 br 태그는 필요없으므로 html1로 지정했습니다. $wr_subject = addslashes(trim($subject)); $wr_content = addslashes(trim($contents)); $wr_link1 = ""; $wr_link2 = ""; $wr_email = ""; $wr_name = addslashes($bo[bo_use_name] ? $mb[mb_name] : $mb[mb_nick]); $sql = " insert into $write_table set wr_num = '$wr_num', wr_reply = '$wr_reply', wr_comment = 0, ca_name = '$ca_name', wr_option = '$html,$secret,$mail', wr_subject = '$wr_subject', wr_content = '$wr_content', wr_link1 = '$wr_link1', wr_link2 = '$wr_link2', wr_link1_hit = 0, wr_link2_hit = 0, wr_hit = 0, wr_good = 0, wr_nogood = 0, mb_id = '$mb_id', wr_password = '', wr_name = '$wr_name', wr_email = '$wr_email', wr_homepage = '', wr_datetime = '".G5_TIME_YMDHIS."', wr_last = '".G5_TIME_YMDHIS."', wr_ip = '{$_SERVER['REMOTE_ADDR']}', wr_1 = '', wr_2 = '', wr_3 = '', wr_4 = '', wr_5 = '', wr_6 = '', wr_7 = '', wr_8 = '', wr_9 = '', wr_10 = '' "; sql_query($sql); $wr_id = sql_insert_id(); sql_query(" update $write_table set wr_parent = '$wr_id' where wr_id = '$wr_id' "); sql_query(" insert into {$g5['board_new_table']} ( bo_table, wr_id, wr_parent, bn_datetime, mb_id ) values ( '{$bo_table}', '{$wr_id}', '{$wr_id}', '".G5_TIME_YMDHIS."', '$mb_id' ) "); sql_query("update {$g5['board_table']} set bo_count_write = bo_count_write + 1 where bo_table = '{$bo_table}'"); return true; } $bo_table = "1234"; // 게시판 테이블을 입력합니다. $mb_id = "guest01"; // 작성자 id를 입력합니다. id가 존재하지 않으면 공백으로 출력되는 문제가 발생합니다. $subject = "기상예보 - ".$today_date."일 발표"; $result = board_write($bo_table, $subject, $contents, $mb_id); echo "Success!"; // 뭔가 밋밋해서 일종의 로그로 넣었습니다 ㅠㅠ } ?>
이 스크립트를 브라우저에서 실행시킨 후에 게시글 목록을 확인하면
다음과 같이 새 게시글이 작성된 것을 확인할 수 있습니다.
해당 게시글을 클릭하면 다음과 같은 내용의 기상예보가 포함되어 있음을 확인할 수 있습니다.
참고로 원래 tenki.jp의 화면은 다음과 같습니다.
보충 설명을 드리면 요새 Accuweather나 일본기상협회를 참고하시는 분들이 많이 계셔서
이 사이트의 정보를 가져오는 것으로 연습을 했습니다.
(참고로 Accuweather의 우리나라 일기예보 API는 유료이고, 웹페이지는 동적 웹페이지입니다)
제가 일본어를 전혀 할 줄 몰라서 착각한 것인지는 몰라도
아쉽게도 tenki.jp에서 우리나라 일기예보는 API로 제공하지 않더군요 ㅠㅠ
그래서 부득이 이 부분은 파싱을 할 수밖에 없었습니다.
사실 예전에 Simple HTML DOM Parser 연습을 위해 작성해본 스크립트라서 군더더기가 많아서 부끄럽네요 ㅜㅜ
그리고 네이버 파파고 API와 관련하여 말씀드리면 NMT와 SMT 두 종류가 있는데
구글링 해보면 대체로 NMT가 더 성능이 뛰어나다고 써있고, 제가 생각하기에도 대부분의 경우에 그럴 것 같습니다.
그런데 제가 번역하려고 하는 일기예보 단어에 있어서만큼은 SMT가 보다 우리말에 근접한 번역을 하더군요.
다만 "세이이치 비"라는 한본어(?) 번역 결과가 나와서 부득이 이 부분은 "맑음 때때로 비"로 강제변경 해줬습니다.
사실 "맑고 때때로 비" 또는 "맑지만 때때로 비"가 논리상으로나 일상에서 사용되는 어휘로서 보다 적절하다고 생각되지만
"맑음 때때로 흐림", "맑음 때때로 눈" 등 유사한 단어의 번역이 그런 형식으로 되어서 부득이 그렇게 변역했습니다.
여담이고 어디까지나 제 추측이지만 네이버 포털에서 제공하는 번역기는
아마도 NMT와 SMT 방식을 조합한 최상의 결과물을 보여주는 것으로 추측되네요.
PHP로 머신러닝을 하는 방법을 제가 알지도 못하고 아무래도 이 스크립트의 범위를 벗어나는 것 같아서
간단히 "세이이치 비"만 변경하도록 했지만 앞으로 제가 예상하지 못한 다른 한본어(?)가 튀어나올 수도 있겠네요 ㅠㅠ
뭔가 그누보드에 아주 조금 적응한 것 같은데 라이믹스로 갈아타려니 아쉬운 마음도 드네요 ㅜㅜ
허접한 스크립트와 설명 읽어주셔서 감사합니다!
그럼 편안한 저녁 되세요 ^-^