Help us understand the problem. What is going on with this article?

ChatWorkのデータをcsvバックアップ.ついでにSlackへ・・・

先に謝罪しておきます.
Qiita初投稿です.
読みづらい点あると思います.
ごめんなさい.

Chatworkのデータをcsvでバックアップしておきたい!

なんらかの事情があって,ChatWorkのデータをcsvで手元に置いたり印刷したい!
そんな人もいるのではないでしょうか?

まぁ,だいたいエクスポート機能あるやろ....
と思っているあなた.

公式ページのよくある質問
https://help.chatwork.com/hc/ja/articles/203352770-%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%92%E4%BF%9D%E5%AD%98%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%81%8B-%E5%8D%B0%E5%88%B7%E3%81%AA%E3%81%A9-

恐れ入りますが、現時点ではチャットのログの保存機能や印刷機能はありません。
なお、エンタープライズプラン、およびKDDI Chatworkにはチャットログのエクスポート機能があります。
フリープラン、パーソナルプラン、ビジネスプランではエクスポート機能はありませんので
コピーペーストなどでログを保存・印刷してください。

まじですか!
コピペですか!

フリープランの私は,
コピペ保存というワードと
エクスポート機能がないことに驚きました...

こういうのって,だいたいツール出てるよね〜
っとqiitaを見てみれば一応参考はあったものの, 

ChatWorkのAPI仕様変更やらで,なにやら不穏な気配...

プランアップグレードして課金するか....
どうしよう....

よし,domから抜くか!

ということで,簡単に概要を説明

  • web版のchatworkを表示
  • chrome開発者ツールのコンソールを表示
  • 画面サイズをモバイルにして読み込み
  • 「タップして過去のメッセージを読み込む」クリックしてバックアップしたいとこまで読み込む
  • 以下のjavascriptを開発者ツールのコンソールから実行
  • コンソールに整形されたデータが出力される
  • 整形されたデータを煮るなり焼くなり
  • もはやコピペと変わらないんじゃ
  • コピペで保存よりは整形して出力できる・・・かな

ということで実際にやっているスクショがこちら.

スクリーンショット 2020-01-15 0.11.16.png

スクリーンショット 2020-01-15 0.15.48.png

webブラウザ上に表示されているデータはたいてい構造化されているので,
チャット形式のような形式が決まっているものであれば,割と簡単に文章を抽出できます.

やっていることは,ブラウザで読み込んだhtmlの構造をみて,整形し,コンソールに表示しているだけです

PC表示だと上にスクロールしまくって過去の投稿を読み込ませなければいけないのですが,
スマホ表示にしておけば,「タップして過去のメッセージを読み込む」のクリックで過去の表示読み込みができます.
(最初の画像の赤矢印のところ)

ChatWorkに限らず,スマホ表示にした場合に構造が見やすくなったり
諸々の手順が楽になる事例は他にも有ると思いますので知っておくといいかも.

あとは,javascriptできれば,応用して使えると思います.
以下は試しにslack用のcsvインポート形式に合わせて整形しています.

無理矢理なところあります,あくまでも参考に...

/**
* Chatwork to csv to Slack script 
*
* 「スマホ表示」のWeb版Chatworkのコンソールに
* 以下のスクリプトを貼り付けて使用する.
* PC表示時のdomよりシンプルなので,処理が楽?と思ったのでやってみた
*/

//-------状況に合わせて変更-----------
function changeUserName(str){
    //return str; //名前をそのまま使いたい場合はそのままリターンしてください

    if(str==='チャットワークユーザ名1'){ //適に変更してください
        return 'UFS******';    //適に変更してください
    }
    else if(str==='チャットワークユーザ名2'){ //適に変更してください
        return 'UHH******';         //適に変更してください
    }
}
var slackChannelName = '#インポートテスト'; //適に変更してください
//----------------------------------


//SlackのcsvインポートはUnixタイム指定なので,chatwork上の文字列から変換.
//Yearは2019で決め打ちしちゃってます!
//TODO:要修正
function strToUnixTime(str){
    //return str; //日付をそのまま使いたい場合はそのままリターンしてください

    var split = str.split(' ');
    var md = split[0];
    md = md.replace('','/');
    md = md.replace('','');
    var ymd = '2019/' + md + ' ';
    var allstr = ymd + split[1];
    var dateobj = new Date(allstr);
    return parseInt( dateobj /1000 );
}

//出力用の配列.これを最終的に出力します.
var arr = [
    ['ts', 'team', 'user', 'text']
]
var cachDate;
var cashUser;


//タイムラインのチャット部分を取得し,投稿の数だけループ
$('#cw_timeline').find('.ui_chat').each((idx, item) => {

    //この変数に一行分(一投稿)のデータを入れていきます
    var field = []

    //日付を抜き出して挿入
    //TODO:雑に抜き出しているので要修正
    if ($(item).find('.ui_chat_date').length > 0) {
        var t =  $(item).find('.ui_chat_date').text().trim();
        if( t.includes("") ){
            cashDate = t;
        }else{
            var month = cashDate.split(' ');
            t = month[0] + ' ' + t;
        }
        t = strToUnixTime(t);
        field.push( '"'+ t +'"' );
    } else {
        field.push('');
    }

    //チャンネル名を挿入
    field.push( '"'+ slackChannelName + '"' );

    //ユーザー名を挿入.連続投稿はユーザー名が無いパターンがあるので前投稿のキャッシュで埋める
    if ($(item).find('.cw_chat_name').length > 0) {
        var name = $(item).find('.cw_chat_name').text();
        if(name===''){          
            field.push( '"' + changeUserName(cashUser) +'"' );          
        }
        else{
            field.push( '"' + changeUserName(name) +'"' );
            cashUser = name;
         }
    }
    else {
        field.push( '"' + changeUser(cashUser) +'"' );
    }

    //本文を抜き出して挿入
    var message = $(item).find('pre').text().replace(/(\r\n|\n|\r)/g, "");
    field.push( '"'+ message +'"' );
    arr.push(field)
});

//コンソール出力
arr.forEach((value) => {
  console.log( value[0] + ','  + value[1] + ','  + value[2] + ','  + value[3] );
});

補足

のちにSlackでインポートするために,ChatWork上のユーザ名をSlackのUserIDに置き換えています.

console出力した一行ずつはこんな形になりますが,
>"1563328680","#インポートテスト","UFSRY3QEN","マイチャットを作成しました。" VM283:84

コンソールからコピペした場合に
最後のVM283:84みたいなやつが余分で付いてきてしまうので,
適当なテキストエディターで置換して一括削除してください.

excelにもインポートしたりして使ったりできます.

スクリーンショット 2020-01-15 0.18.42.png

ちなみに,

//コンソール出力
/*
arr.forEach((value) => {
  console.log( value[0] + ','  + value[1] + ','  + value[2] + ','  + value[3] );
});
*/
window.open(encodeURI("data:text/csv;charset=utf-8," + arr.map(e => e.join(",")).join("\n")))

みたいにすれば,csvでそのまま出力できます.
ただ,自分の環境では大量のデータだと出力に失敗することがあり,
最終的にはコンソール出力でコピペしました.

ChatworkからSlackへのインポートのために

  • 文字列の日付情報から,UNIXタイムスタンプへ変更しなければならない.
  • 同一ユーザの連続投稿は,ユーザ名情報が無いパターンが存在するので,その対応をする.
  • "UNIXタイムスタンプ","チャンネル名","ユーザ名","本文" 形式のcsvがSlackのインポート形式

このポイントを押さえて,整形すればインポートできます.
上記のjavascriptのサンプルでは,ChatWork上の時間文字列からUNIXタイムスタンプへ変換して出力しています.

※日付を2019年に決め打ちで作ってしまっているので,時間があれば修正します.

スクリーンショット 2020-01-15 0.25.35.png

あとは,Slackのcsvインポートのところでインポートさせてあげれば完了です.

ちゃんとインポートされるまで,いくつか手順をふみますが,
以下のようになれば完了です!

スクリーンショット 2020-01-15 0.28.48.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away