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
번호 분류 제목 글쓴이 날짜 조회 수
38 코드 [JS] http를 https로 리디렉션! 3 Hanam09 2018.12.30 674
37 자료 이게 팔릴까 - Xe/라이믹스 에러페이지 [2017-10-04] 3 file title: 열려라 맛스타의 자물쇠TVJ 2017.10.04 671
36 코드 [아미나] 출석 여부를 나타내는 메인화면 위젯 4 file 이니스프리 2018.12.15 666
» 코드 [PHP] 그누보드 자동 게시글 작성 - 일본기상협회의 우리나라 날씨를 크롤링한 후 파파고로 번역하여 글 작성 4 file 이니스프리 2018.11.15 655
34 코드 html 초보가 만든 자소서 4 title: 대한민국 국기gimmepoint 2018.04.21 651
33 코드 Git 저장소에서 자동으로 받아 업데이트하는 쉘 스크립트 5 NoYeah 2017.09.16 650
32 자료 AdBlock 접근 방지 애드온 v0.1 3 file 네모 2017.10.05 648
31 코드 [PHP] 기상청 중기예보를 캐러셀로 보여주는 위젯 (매우 허접합니다 ㅠㅠ) 10 file 이니스프리 2018.09.28 647
30 코드 [Python/Telegram] Studyforus 알림봇 (댓글, 스티커 파싱) 7 file 이니스프리 2020.05.15 644
29 코드 Cmd 에서 서비스 시작 / 종료하기 1 ProjectSE 2018.02.18 644
28 코드 브라우저 언어에 따라 다른 폴더를 사용하는 PHP 코드 4 file 네모 2017.10.10 639
27 자료 Gentelella 레이아웃에 사용가능한 가격 테이블 위젯입니다. 3 file NoYeah 2017.07.03 637
26 코드 [아미나] 게시글을 작성하면 ID와 IP로 필터링하여 자동으로 랜덤 댓글을 남기기 (+랜덤 포인트) 7 file 이니스프리 2018.11.18 634
25 자료 [Bootstrap] xeACE 레이아웃 3 title: 은메달도다 2017.09.17 632
24 코드 [JS]클라이언트에서 Ip를 얻어보자 2 Hanam09 2019.01.21 625
23 자료 경험치 현황 위젯 6 file NoYeah 2017.06.28 622
22 코드 [PHP] 간단한 캐싱 클래스 3 title: 황금 서버 (30일)humit 2018.12.06 605
21 자료 [XE / Rhymix] Bootstrap 패널 위젯 스타일 file title: 은메달도다 2017.08.09 603
20 자료 [1.8a] Bootstrap 'Panel' 위젯 스타일 1 file title: 은메달도다 2017.08.09 602
19 코드 매우 특이한 버그 9 title: 대한민국 국기gimmepoint 2018.06.05 569
Board Pagination Prev 1 2 3 4 Next
/ 4