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 코드 폰트를 자동 설치하는 코드 1 네모 2018.07.16 977
77 코드 파이썬을 이용한 텔레그램 새 글 알림 (허접합니다) 4 이니스프리 2017.11.19 2520
76 코드 파이선 셸에서 실행하면...? 3 제르엘 2018.07.22 546
75 코드 클라이언트단에서 이미지 리사이징 6 file 네모 2018.05.06 1155
74 코드 컴퓨터의 uuid 얻기 5 title: 황금 서버 (30일)humit 2018.01.28 1239
73 코드 잘못 쓰면 컴퓨터가 날아가는 코드 29 제르엘 2018.07.08 1022
72 자료 이게 팔릴까 - Xe/라이믹스 에러페이지 [2017-10-04] 3 file title: 열려라 맛스타의 자물쇠TVJ 2017.10.04 753
71 코드 유튜브에 약간의 기능을 추가 해주는 크롬 확장 프로그램. 11 file Hanam09 2018.01.26 1078
70 코드 엑셀파일 불러서 히스토그램 그려주는 함수 국내산라이츄 2017.08.03 881
69 코드 엑셀 읽어서 그래프 그려주는 함수 1 국내산라이츄 2017.08.03 1555
68 코드 아주 간단한 기초 C++ 6 제르엘 2018.04.21 570
67 자료 소셜XE / 기존 통합 로그인 스킨 V2.2 2 file NoYeah 2017.06.28 1072
66 코드 세린서버에서 시도중인 백업 스크립트 입니다. 4 NoYeah 2017.06.27 837
65 코드 새 글 자동 댓글 스크립트 (AutoHotkey) 9 이니스프리 2017.11.26 3565
64 코드 사이트 서버 이전 (또는 미러링 사이트 구축) 쉽게하는 스크립트 1 NoYeah 2018.01.14 1043
63 코드 브라우저 언어에 따라 다른 폴더를 사용하는 PHP 코드 4 file 네모 2017.10.10 880
62 코드 미완성 받아쓰기 (C) title: 대한민국 국기gimmepoint 2018.04.20 578
61 코드 매우 특이한 버그 9 title: 대한민국 국기gimmepoint 2018.06.05 729
60 자료 링크 파싱 애드온용 스킨 (트위터 스타일) 3 file SNAX 2017.10.03 583
59 코드 도박 중독자를 위한 광고 차단 규칙 file 제르엘 2020.08.21 440
Board Pagination Prev 1 2 3 4 Next
/ 4