Extra Form
라이선스 MIT

안녕하세요?


작년에 humit 님과 네모 님의 도움으로 작성했던 그누보드(아미나) 자동 글 작성 스크립트를 보완하여,


일본기상협회(tenki.jp)의 우리나라 날씨를 파파고 SMT로 번역한 후


그누보드에 자동으로 게시글을 작성하는 스크립트를 작성했습니다.


이 글을 빌어 humit 님과 네모 님께 다시 한 번 진심으로 감사드립니다! :)



우선 이 스크립트는 어디까지나 연습용임을 감안해주시고 연습 용도로만 사용해주시기를 부탁드립니다 ㅠㅠ


제가 나중에 제대로 된 사이트를 오픈하게 되면


초기에 게시판이 너무 썰렁한 경우에 저작권법을 준수하는 범위 내에서 응용해서 사용하려고 하네요 ^^



그누보드 게시글 자동작성 함수와 관련해서는 도와주세요 게시판에 제가 올렸던 글을 참조하시면 됩니다.


https://studyforus.com/index.php?_filter=search&mid=help&search_target=title&search_keyword=%EC%9E%90%EB%8F%99&document_srl=274040


당시에 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로 머신러닝을 하는 방법을 제가 알지도 못하고 아무래도 이 스크립트의 범위를 벗어나는 것 같아서


간단히 "세이이치 비"만 변경하도록 했지만 앞으로 제가 예상하지 못한 다른 한본어(?)가 튀어나올 수도 있겠네요 ㅠㅠ



뭔가 그누보드에 아주 조금 적응한 것 같은데 라이믹스로 갈아타려니 아쉬운 마음도 드네요 ㅜㅜ


허접한 스크립트와 설명 읽어주셔서 감사합니다!


그럼 편안한 저녁 되세요 ^-^


  • ?
    도토리묵 2018.11.17 00:55
    오! 이거 잘만 활용하면 XE에서도 사용할수 있겠네요.
    감사드립니다.
    근데 왜 No Más! 이신지 ㅋㅋㅋ?
    No more 이라는 뜻 아닌가요?
  • profile
    이니스프리 2018.11.17 03:48

    오늘은 어쩌다보니 회식이 너무 길어졌네요 ㅠㅠ (현재 서울은 불금입니다)

    스페인어 No Más는 영어로 No more 맞아요 ^^

    XE에 대해서는 제가 잘 모르지만 테이블 구조가 상당히 다를테니 많이 수정하셔야 될거에요.

    (제가 아직 XE나 라이믹스로 넘어가지 못한 이유 중 하나네요 ㅠㅠ)

    그럼 즐거운 금요일 되세요~!

  • ?
    도토리묵 2018.11.17 04:20
    이쯤되면 이니스프리님이 운영하는 사이트가 궁금해지는군요 ㅋㅋ
  • profile
    이니스프리 2018.11.17 04:27
    저는 고수가 아니라서요~! ^^
    내년에 좀 더 그럴듯한 사이트를 만들면 공개하겠습니다 :)

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
78 자료 AdBlock 접근 방지 애드온 v0.1 3 file 네모 2017.10.05 745
77 자료 AdminLTE용 에디터 스타일 4 file title: 은메달도다 2017.07.07 837
76 코드 AWSCLI, in a single file (portable, linux) 1 file Seia 2021.04.10 312
75 코드 c 이진트리 전,중,후위 알고리즘 2 title: 대한민국 국기gimmepoint 2018.04.24 644
74 코드 Cmd 에서 서비스 시작 / 종료하기 1 ProjectSE 2018.02.18 698
73 코드 CMD로 로컬 연결 고정 IP 설정하기 1 title: 황금 서버 (30일)humit 2018.02.06 1092
72 코드 C언어 삼중자를 이용한 코드 title: 황금 서버 (30일)humit 2018.07.22 484
71 자료 even_move - 감성적인 에러 페이지 7 file title: 열려라 맛스타의 자물쇠TVJ 2017.08.08 897
70 자료 Gentelella 3 file NoYeah 2017.06.29 1061
69 자료 Gentelella 레이아웃에 사용가능한 가격 테이블 위젯입니다. 3 file NoYeah 2017.07.03 694
68 코드 Git 저장소에서 자동으로 받아 업데이트하는 쉘 스크립트 5 NoYeah 2017.09.16 769
67 코드 Hello, World!를 출력해보자 18 네모 2018.04.21 661
66 코드 HEX를 RGB로, RGB를 HEX로 바꾸는 PHP 코드 1 네모 2018.05.05 678
65 코드 html 초보가 만든 자소서 4 title: 대한민국 국기gimmepoint 2018.04.21 740
64 코드 JavaScript에서 파이썬 문자열 처리 함수 중 하나 (바인딩)를 구현 7 Seia 2020.01.20 564
63 코드 Koa에서 자동으로 라우팅 채워주기 Seia 2020.01.22 662
62 자료 RBGE - 이쁘고 깔끔한 에러페이지 4 file title: 열려라 맛스타의 자물쇠TVJ 2017.08.08 771
61 자료 [1.8a] Bootstrap 'Panel' 위젯 스타일 1 file title: 은메달도다 2017.08.09 678
60 자료 [Autohotkey] 매분 정각에 전체화면을 캡쳐하는 스크립트 4 file 이니스프리 2020.05.22 1242
59 자료 [Bootstrap] xeACE 레이아웃 3 title: 은메달도다 2017.09.17 727
Board Pagination Prev 1 2 3 4 Next
/ 4