日記

  • puppeteer すぐ使える取得例

    いろんな記事見ても、うーむわからん!取得できん!
    となって、うまく動かないことが多かったので、試行錯誤の末とりあえず動いた例をここにおいておきます。

    リストが並んでてそこから情報を取り出したい
    ということが多いと思いますが、そういったときにだいたい使えると思います。

    はてなブックマークの人気エントリーのリストから取り出す

    そんな例です。ブックマーク数、タイトル、URLを抜き出して配列にしています。
    コンソールに、結合してから出力しています。

    
    const puppeteer = require('puppeteer');
    
    (async () => {
        const browser = await puppeteer.launch({ 
            //executablePath: '/usr/bin/chromium-browser',
            args: ['--no-sandbox'],
            //見えるようにfalseにしたけど本番はtrueにしてね
            headless:false
        });
    
        //配列を作る
        var text = [];
        
        const page = await browser.newPage();
        await page.goto('http://b.hatena.ne.jp/hotentry/all',{ waitUntil: 'domcontentloaded' });
        //await page.waitFor(2000);
    
        //情報を取り出したい同列に並んでいる要素(liとかが多い)
        const items = await page.$$('#container > div.wrapper > div > div.entrylist-main > section > ul > li > div > div.entrylist-contents-main');
    
        //取り出したい内容のselectorをなんとかして選ぶ
        const inner1 = await page.$$('#container > div.wrapper > div > div.entrylist-main > section > ul > li > div > div.entrylist-contents-main > h3 > a');
        const inner2 = await page.$$('#container > div.wrapper > div > div.entrylist-main > section > ul > li > div > div.entrylist-contents-main > span > a');
        
        //要素分ループを回す
        for (let i = 0; i < items.length; i++) {
            //取得
            const text1 = await page.evaluate(content => content.innerText, inner1[i]);
            const text2 = await page.evaluate(content => content.innerText, inner2[i]);
            const text3 = await page.evaluate(content => content.href, inner2[i]);
            //配列に追加していく
            text.push( text1 + " 【" + text2 + "】\n" + text3 + "\n"); 
        }
    
        //配列を全て結合
        text = text.join("");
    
        //結合した配列を出力
        console.log(text);
    
        await browser.close();
    })();

    itemsが並んでる要素。
    innerが取り出したい中身です。上記の図でわかるでしょうか。

    こういうパターンもありますね。赤が「items」青が「inner」になります。

    セレクターをうまく取り出す方法

    セレクターがうまく指定できてないことが動かない原因であることが多いです。
    デベロッパーツールでセレクターを取得する方法です。

    chromeのデベロッパーツールを開き、その要素の上で右クリック。
    Copy > Copy selector と選ぶとその場所のセレクターがコピーできます。
    どこかにペーストしてください。

    #container > div.wrapper > div > div.entrylist-main > section > ul > li:nth-child(1) > div > div.entrylist-contents-main > span > a

    こんな感じになります。「何個め」を表す:nth-child はループさせるときに邪魔になるので

    #container > div.wrapper > div > div.entrylist-main > section > ul > li > div > div.entrylist-contents-main > span > a

    このように少し削除して上記のサンプルでは利用しています。

    まとめ

    スクレイピングは元サイトに迷惑をかけないようマナーを守ってやりましょう!
    訴えられた例もあるので注意してね。 https://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6


  • Node.js で チャットワークにメッセージを送る

    参考にしました。

    https://qiita.com/dokkoisho/items/f95bbe96fe4bd7312f40

    APIを設定

    まずトークンを発行してください

    https://www.chatwork.com/service/packages/chatwork/subpackages/api/token.php

    ルームID

    部屋のridxxxxxxxの数字の部分です。
    送りたい場所のものを控えておいてください。

    コード

    request を使うのでインストール。

    $ sudo npm install request

    message.js

    const request = require('request');
    const room_id = "xxxxxxxxxxx"; //メッセージを送りたいchatのURL末の番号(数字部分のみ)
    const apiToken = "xxxxxxxxxxxxxxxxxxxxx"; //APIトークン
    
    /* IDの情報取得に利用
    function getInfo(){
        const options = {
            url:"https://api.chatwork.com/v2/me",
            headers:{
                "X-ChatWorkToken":apiToken
            }
        }
        function callbackFuc(error, res, body){
            //res(HTTPレスポンスヘッダ)
            //body(HTTPレスポンスボディ) jsonで返される
            res.statusCode == 200 ? console.log(body) : console.log('error: ' + error + '\nresponseCode: ' + res.statusCode);
        }
        request.get(options,callbackFuc);
    }
    getInfo();
    */
    
    //メッセージの送信
    function sendToMychat(){
        const options = {
            url:"https://api.chatwork.com/v2/rooms/" + room_id + "/messages",
            headers:{
                "X-ChatWorkToken":apiToken
            },
            form:{
                body:"メッセージ送信テストです"
            }
        }
        function callbackFuc(error, res, body){
            res.statusCode == 200 ? console.log(body) : console.log('error: ' + error + '\nresponseCode: ' + res.statusCode);
        }
        request.post(options,callbackFuc);
    }
    sendToMychat();

    実行

    $ node message.js

    puppeteerで取得してきた情報をチャットワークに出力するのもいいかもしれませんね。

    https://logzitsu.tlog.work/headless-chrome/
  • 【12/6まで】ヨドバシのお年玉企画が抽選受付中だよ

    受付場所はこちら

     商品は以下の通り。

    買おうと思ったけど、ちょっとためらってるんだよな・・・というのは抽選に参加してみるといいかもしれませんね。

    どれもさすがの倍率です。

  • Zaifにものすごくお願いされている件について

    Zaifってメルアドとパスワードだけで登録できて、あとで名前やら住所やら登録する仕組みだったのです。
    でも途中で飽きて登録したまま色々入力せず放置してました。

    https://coinpost.jp/?p=46976

    どうやら、ハッキング事件が起きたらしくてんやわんやになってたみたいですね。
    で、フィスコとやらと資本提携したみたいです。

    その引き継ぎに同意してくれってすごくメールが来ます。
    いやだわ。

    アカウント数で色々かわるから必死なんだろうな。
    がんばって!!!

    メールアドレス登録変えたんだけど、古いアドレスに送ってくるのだけはやめてくれー

  • Node.jsのプログラムを定期的に実行する

    毎週実行とか、毎日何時に実行とか、そういう動きをさせたいプログラムがあると思います。
    そんな時に使える2つを紹介します。

    どっちかを導入してみてね。違いはよく知らん。

    node-schedule

    $ npm install node-schedule

    app.jsを毎日13時に実行させたい場合です。

    schedule.js

    let schedule = require('node-schedule');
    let app =require('./app.js');
    
    let j000 = schedule.scheduleJob({hour : 13,minute: 0}, function(){
      app.post();
     });

    app.js側

    exports.post = function (){
    
    console.log("実行しました");
    
    };

    実行

    $ node schedule.js

    node-cron

    $ npm install cron
    $ npm install time

    schedule-cron.js (app.jsは上と同じ)

    const {CronJob} = require('cron');
    let app =require('./app.js');
    
    //秒: 0-59 分: 0-59 時: 0-23 日: 1-31 月: 0-11 週: 0-6
    //以下は毎日 10:45
    new CronJob('00 45 10 * * *', () => {
      app.post();
    }, null, true); 

    実行

    $ node schedule-cron.js

    さらに、これらはPM2と組み合わせると良いですよ。

    https://logzitsu.tlog.work/%E5%91%BD%E4%BB%A4%E3%82%92%E3%83%87%E3%83%BC%E3%83%A2%E3%83%B3%E5%8C%96%E3%80%82node-js-pm2%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86/
  • 命令をデーモン化。Node.js PM2を使おう

    nodeはターミナル画面を立ち上げてる間に処理をするのが基本なんですが、ターミナル画面を閉じてしまうと処理が止まってしまいます。

    ずっと立ち上げとけばいいのですがあまり現実的ではないですね。

    そんなときにPM2

    ずーーーっと動かしたいタスクを登録しておくと便利です。
     意図的に止めたり、エラーが起きない限りは裏で動いててくれます。

    インストールします

    $ sudo npm install pm2 -g

    多分グローバルにインストールしないとダメです。

    $ pm2 start app.js

    上記で登録できます。(app.jsを動かす場合)

    動作状況確認は

    $ pm2 ls

    登録解除は

    $ pm2 stop app.js

    こんな感じでーす。

    起動で実行するようにする

    上記はラズパイで動かしているのですが、
    再起動した時に自動的に起動して欲しいことがあると思います。
    まず、起動したいものがPM2でぜんぶ動いている状態にしてください。その状態で立ち上がります。
    再起動時になって欲しい状態を作ったら

    $ pm2 startup ubuntu

    上記はubuntuの場合ですね。他の環境の場合はよくわかりません。
    そうすると、このコマンドを打ってね、みたいなメッセージが出るのでその通りにします。
    自分の環境に場合は以下のようなメッセージでした。

    $ sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup ubuntu -u ubuntu --hp /home/ubuntu

    そのあとにそれを保存するため以下を実行します。

    $ pm2 save

    再起動して立ち上がればオッケーです。

    $ sudo reboot
    https://logzitsu.tlog.work/node-js%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E5%AE%9A%E6%9C%9F%E7%9A%84%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B/
  • 「いらすとや」がグッズ展開してるみたいだよ

    フリー素材として有名ないらすとやですが、意外とあの絵柄にファンは多いみたいです。

    日本中どこでも見かけますし、知名度はハンパないでしょうしね。

    LINEスタンプ

    公式のラインスタンプが結構出てます。
    実際使うスタンプって送り手と受取手がどっちも知ってないと厳しい。
    そういう意味では使いやすいですよね。

    https://store.line.me/stickershop/author/4325/ja

    ゲームプライズ

    ストラップ付きのぬいぐるみですね。かわいい。
    UFOキャッチャーとかで取れる店があるようです。

    https://charahiroba.com/prize/item/detail?id=6174

    ガチャガチャ

    一個500円。ちょっと高いですけどよくできてますね。

    TBSニュースのキャスター

    グッズじゃないですけど、読み上げのアバターになってるみたいです。

  • PremiaでDVDを焼く方法

    基本的にはリンク先を参考にしてください。
    この記事は愚痴です。

    参考
    https://design1plus.net/premiere-encore/

    https://logzitsu.tlog.work/%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC%E3%82%92premia%E3%81%A7%E7%B7%A8%E9%9B%86%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/

    この記事の続きです。

    なんかプレミアCS6についてた古いソフトがいるらしい。めんどくさいなぁ。

    メディア書き出しで上記のような設定で書き出してください。

    creativeクラウドから premia CS6をインストールしておいてください。
    実際に使うのは

    こいつです。

    その後の設定は一番上のリンクを参考にしてください。

    DVD作るのマジでめんどくさいなぁ。
    youtubeは手軽ですごいってのがよくわかりました。

  • デスクチェア嫌いマンがオススメする作業用ソファー

    デスクチェアを部屋におくのがあまり好きではない

    家で作業するんですけど、デスクチェアというのがあまり得意ではありません。
    なぜかというと、なんだかかさばる感じで部屋に置いておくとすごく存在感があるし、ローラーついている足はすごく床を痛めそうだな・・・という印象があるからです。

    また、作業用のチェアは人間工学に基づいて作られていて、体にフィットする感じになっています。
    それはそれで長時間快適に過ごすことができるのでしょうが、個人的にはベンチみたいな長椅子のようなもので体制をすぐに変えながらやったほうが快適に過ごせる気がしています。

    すぐに体を動かしたくなっちゃうんですよね。寝そべったり。

    ベンチを部屋に置くのもいいけど、ソファーで作業すりゃいいじゃん!

    だから私のメイン戦場はソファーなのです。
    ソファーだったら仕事もできるしご飯も食べれるし、接客にも使えるし、ちょっと昼寝にも使えるのです。そういう万能さが一人暮らしには求められていると思いませんか?
    寝るなら座面が結構長くないといけないんですけど、一人暮らしだと1.5〜2人掛けのソファーがオススメですよ。

    オススメソファーを探してみました

    いろんなソファーを探してみました。自分が使ってるのと近いものから紹介します。

    不二貿易 バイキャストPUソファ フレンズ 2人掛け 合成皮革 ダークブラウン 71157

    自分の使ってるのはこれに近いものです。
    ちょっと男らしい部屋にしたいな、と思ってる人にはオススメです。
    部屋に雰囲気が出ます。ただ、肘掛けが寝る時に邪魔です。
    これがなければベッドの代わりにもなったのになーというのが惜しい。

    価格もお手頃です。でもソファーは捨てるの大変だから、安いからという理由で買わないほうがいいです。ちゃんと選びましょう。
    自分は半年ほど使ってますが、超満足ですね。オットマンも使ってます。
    また、合皮の寿命はあまり長くないみたいなのでそこは割り切って買いましょう。

    アイリスプラザ ソファ 2人掛け ブラウン 幅115㎝ EJ-2107

    アマゾンでベストセラーの商品です。
    このブログでワークチェアも紹介しているアイリスプラザですね。
    何と言っても特徴は安いことですね。
    レビューも概ね評価が高いです。
    低い評価は、パーツ欠損で届いたというものなので、交換対応してもらえるでしょうしちゃんと届けば問題ないものなのだと思います。

    アイリスプラザ ソファ カウチ 2人掛け クッション付き あぐら チャコールグレー 幅約110㎝ 34136

    まーたアイリスプラザですね。オットマンがついて、肘掛けが片方なくて寝やすそうだし、安いし使いやすそうで最高じゃないですか!

    じぶんがさがしたときにこれがあればもしかしたらこれを買っていたかもしれません。
    ミニマリストならメインベッドとして使ってもいいんじゃないでしょうか。
    そういう生活したいなぁ。

    まとめ

    ソファーで長時間作業は快適なのですごくオススメ!

  • あと1カ月だぞ、何で今までほっといた?iPhoneバッテリー交換を予約せよ!

    iPhoneのバッテリーでわざとパフォーマンス下げてる疑惑があり、その対応で今年いっぱいバッテリー交換が非常に安くできるようになってます。

    いくらで交換できるの?

    公式サイトから引用。3,200円で期間過ぎても5,400円みたいですね。
    iPhone X とかはまだやらなくていいんじゃないかな。
    そんなに高くないかなって個人的には思います。

    とりあえずサポートアプリを入れよう

    こちら → https://itunes.apple.com/jp/app/apple-%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88/id1130498044?mt=8

    予約とったりするアプリです。
    配送の場合も手順が表示されますよ。

    代替機がある場合 → 配送修理

    手元に古いiphoneやandroidがある場合はsimを取り替えることで電話番号そのままで使えるので、AppleにiPhoneを送っちゃいましょう。
    ぶっちゃけ予約取るの大変なのでさっさとこれでやりましょう。
    1週間ほどで手元に届くみたいです。

    代替機が「ない」場合 → 予約修理

    この予約がとれないとれない。

    サポートアプリで「バッテリーと充電」から端末を選んで、
    バッテリーと充電 → バッテリー交換 → 持ち込み修理
    と選んでいきます。

    持ち込み修理を選ぶと場所の検索になります。

    上記のような感じになります。
    だいたい脈なしな表示です。もしこんな表示が出たら即刻予約してください。すぐ他の人が手続きして埋まりますので注意。
    上の画面は3箇所予約可能な奇跡!
    1週間後の今頃から予約可能になってることがあります。

    予約可能表示を掴む方法

    「何回も場所検索を繰り返す」これしかありません。
    また、おそらく次の週の今の時間が予約できるタイミングっぽいので、15時25分ごろとか予約が終わるタイミングっぽいところが狙い目なのかもしれません。

    頑張れ

    どこも取れないっぽかったので、場所とかどうでもいいやーって感じで予約しました。
    渋谷の店舗で予約できたのでよかったです。
    あと1ヶ月です。みんなも頑張れ。

    予約が取れた後は

    ・バックアップを取ること
    ・バージョンを最新にすること
    という指示があります。
    それを満たした後、予約時間にGOです。

  • 座面の蒸れ解消!長時間座る方におすすめのワークチェア

    座面の蒸れからの臭い問題

    私は仕事やゲームの際、長時間座っているせいで座面が蒸れて、臭いが気になることがありました。
    以前は3Dメッシュの座布団を使ってましたが、期待している「蒸れゼロ」は流石に無理でした。

    イーサプライ シートクッション メッシュ ハニカム 座布団 丸洗い EEX-CHC01

    最近いいぞアイリスオオヤマ

    昔から良かったのかもしれないですごめんなさい。でもなんか最近でた掃除機とかぶつぶつ・・・

    紹介したいのはこれ。

    座面が、床がすけて見えるメッシュでできているのだ!!

    表面だけそれっぽくて結局綿が入ってる、よくあるあれじゃないですよ。

    エクストラクール・ハイバックチェア HLC-0088-1K

    機能紹介

    腰あて高さ調節機能

    背もたれの裏に腰当てがついており、これがすごくいい。高さが調節でき、自分の体型にあった位置に調節できる。

    首あて調節機能

    背もたれの上についている首当ての角度をある程度調節できます。

    私の場合はなんかしっくり来ないので外してしまいましたが、同居人は気に入ったようでした。

    肘掛け高さ調節機能

    肘掛けの高さを4段階調節できます。

    私は奥行きのあるデスクを使っているので基本肘掛けを使ってません。
    天板上面までの高さが70cmのデスクであれば、肘掛けを一番上まで上げるとかなり快適な高さになります。

    座面の高さ調節機能

    まぁ、大体この手の椅子にはついてるよね。座ったときに座面下右側にあるレバーで調節できます。

    背もたれロック / 解除でぐいーん

    これもまぁまぁついてますよね。

    座ったときに座面下左側にあるレバーで切り替えできます。解除するとぐいーんと背もたれをリクライニングすることが可能。持たれてないと戻ってくる、バネの感じのやつです。座椅子みたいに固定されないので注意。

    ちなみにバネの硬さは座面下前側の突起を回すと調整できます。

    超高い椅子の購入も考えてましたが、これで十分快適です。お試しあれ〜


    エクストラクール・ハイバックチェア HLC-0088-1K
  • CSSにはバージョンがないらしいって話

    CSS3というのはよく聞く単語ですが、実はこれは正しくないらしい。
    CSSの機能は細かくモジュール分割されていて、いてそれぞれのモジュールのレベルという形で表現されているらしい。

    だからCSS3とかCSS4は通称みたいですね。
    新しく追加されるモジュールのレベルは1から始まるらしい。

    ちなみに、CSSとおんなじって訳ではないみたいですが、html5も6に数字が上がることはなく、アップデートが行われてるみたいです。

  • Adobe製品がアマゾンで安い!急げ!

    最大68%OFF!11/30までブラックフライデーSALE とのこと。

    セールは年に何回もないので、Adobe製品欲しかったよ!という人は買い求めたほうがいいです。
    すでに持ってる人も、現在のプランが切れた後に延長で適用できますよ!

    購入はこちら

  • スクレイピングでmac製品をカートに入れる・・・を試して修正した

    元記事です

    PuppeteerでスクレイピングしてMacBook Pro整備済製品をカートに入れる!もう逃さない!
    https://qiita.com/iwamooo/items/4f47d17704cd9b4f1de9

    なんか、Appleのサイトの仕様が変わってるらしくて、うまく動きませんでした。

    const puppeteer = require('puppeteer')
    const notifier = require('node-notifier')
    
    const getMacbook = setInterval(() => {
      !(async() => {
        try {
          const browser = await puppeteer.launch({ 
            //executablePath: '/usr/bin/chromium-browser',
            args: ['--no-sandbox'],
        headless:true })
          const page = await browser.newPage()
          await page.waitFor(5000)
    
          // ページアクセス
          await page.goto('https://www.apple.com/jp/shop/refurbished/mac')
    
          /**
           * findItem
           *
           * @return {object}
           */
          const findItem = await page.evaluate(() => {
            let result = {}
            const nodeList = document.querySelectorAll('.as-producttile-tilelink')
    
            for (let i = 0; nodeList.length > i; i++) {
              const target = nodeList[i].innerText
    
              const check_1 = 'Mac Mini 2.8GHzデュアルコアIntel Core i5 [整備済製品]'
              /* const check_2 = '2017年6月発売モデル' */
    
              if (target.indexOf(check_1) !== -1 /*&& target.indexOf(check_2) !== -1 */) {
                result.isHit = true
                result.itemNumber = i + 1
    
                console.log(result.itemNumber);
    
                break
              }
            }
    
            return result
          })
    
          if (findItem.isHit) {
            // ログイン部分のDOM読み込み(isLogin)
            await page.click('#ac-gn-bag > a')
            await page.waitFor(5000)
    
            /**
             * isLogin
             *
             * @return {boolean}
             */
            const isLogin = await page.evaluate(() => {
              const findItem = document.querySelectorAll('.ac-gn-bagview-nav-item-signIn')
              return findItem.length ? false : true
            })
    
            if (!isLogin) {
              // ページ移動
              await page.click('.ac-gn-bagview-nav-link-signIn')
              await page.waitForNavigation()
    
              // ログイン情報設定
              await page.type('input[name="login-appleId"]', 'Apple ログインID');
              await page.type('input[name="login-password"]', 'パスワード');
    
              // ログイン
              await page.click('#sign-in')
              await page.waitForNavigation()
    
              // ログイン部分のDOM読み込み(isCartEmpty)
              await page.click('#ac-gn-bag > a')
              await page.waitFor(5000)
    
              /**
               * isCartEmpty
               *
               * @return {boolean}
               */
              const isCartEmpty = await page.evaluate(() => {
                const findItem = document.querySelectorAll('.ac-gn-bagview-message-empty')
    
                return findItem.length ? true : false
              })
    
              if (isCartEmpty) {
                // ページ移動
                
                await page.click(`.as-gridpage-producttiles li:nth-child(${findItem.itemNumber}) .as-producttile-tilelink`)
                //await page.click(.box-content > table:nth-child(${findItem.itemNumber}) .product > .purchase-info > a`)
                await page.waitFor('.form-submit-btn', {
                  timeout: 120000
                })
    
                // カートに追加
                await page.click('.form-submit-btn button')
    
                // デスクトップ通知
                notifier.notify({
                  'title': 'アイテムヒット!',
                  'message': 'カートに追加したよ!'
                })
    
                console.log('カートに追加したよ!')
              } else {
                console.log('もうカートにあるよ!')
                clearInterval(getMacbook)
              }
            }
          } else {
            console.log('みつからないなー。。。')
          }
    
          browser.close()
        } catch (e) {
          console.error(e)
        }
      })()
    }, 60000)

    問題点は、検索ワードがぴったりあってないと動かないっぽいところです。
    正規表現とかである程度幅を持たせとかないと逃す気がする。
    すごくテストしとかないと信頼性がないですねー。

    あと、サイトの仕様が変わってるとうまく動きませんね・・・

    応用で何かできないか考えてみたいと思います。
    あと、上記コード試すときはAppleに負荷かけないように心がけて試してくださいー。

  • pupeteerで情報を取得してメール送信してみる

    https://logzitsu.tlog.work/headless-chrome/
    https://logzitsu.tlog.work/node-je%E3%81%A7%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92%E9%80%81%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B%E3%82%88%E3%83%BC/

    上記を組み合わせただけでーす。
    classとか使えばもっといい感じに連携できるのかも知れませんが、今回は愚直にやります。

    お天気情報のメール配信プログラムです

    yahooから天気情報にアクセスして、画像を取得の上、メールに天気情報をのせて送信します。

    いろいろ必要なので事前にインストールしておいてください。

    npm i co
    npm i nodemailer
    npm i fs
    npm i puppeteer
    npm i date-utils
    npm i bluebird

    で、ぜんぶかな(たぶん)

    tenkimail.js

    const co = require('co');
    const mailer = require('nodemailer');
    const fs = require('fs');
    const puppeteer = require('puppeteer');
    //時間
    require('date-utils');
    let now = new Date();
    
    
    (async () => {
        const mail_config = {
          "host": "xxxxxxxxxx.ne.jp", //SMTPホスト
          "port": "587", // ポート
          "auth": {
            "user": "メールアドレス@aaa.aaaa", //ユーザー名
            "pass": "xxxxxxxxxxx" // パスワード
          }
        }
        const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
        const page = await browser.newPage();
        // ページ作成
        await page.goto('https://weather.yahoo.co.jp/weather/');
        await page.waitFor(2000);
    
        // 文章の取得
        console.log(await page.title());
        const texts = await page.$eval('#condition .text', item => { return item.innerHTML });
        console.log(texts);
    
        // スクリーンショット撮影
        let element = await page.$('#forecastMap');
        await element.screenshot({ path: 'screenshot-tenki.png' });
    
        await browser.close();
    
        //SMTPの接続
        var smtp_tmp = mailer.createTransport(mail_config);
        // プロミス化
        var smtp = require('bluebird').promisifyAll(smtp_tmp);
    
        // メール内容の設定
        var mail = {
          from: "メールアドレス@aaa.aaaa", //送信元
          to: "xxxxxxxxxxxxxx@gmail.com", // 送信先
          subject: now.toFormat('YYYY年MM月DD日 HH24時MI分SS秒') + "天気予報", //メールのタイトル
          text: texts, //メール本文
          attachments:[{
            filename: "screenshot-tenki.png",
            content: fs.readFileSync("screenshot-tenki.png")
          }]
        };
    
        co(function*(){
          try{
            var res = yield smtp.sendMailAsync(mail);
            console.log(res);
          }catch(e){
            console.log("Error");
            console.log(e);
          }
          smtp.close();
        });
    })();

    実行は

    node tenkimail.js

    スケジューラーに組み込んだり、PM2でデーモン化したりするといいですよ。

    活用アイデア

    毎日の株価の配信とか?
    30秒ごととかで検索をかけて、条件を満たしたらメールで通知するとかがすごく役に立ちそうな気がします。
    いい使い方があったら教えてください。

  • node.jeでメールを送ってみるよー

    参考にしました

    https://www.yoshi-net.tokyo/%E6%8A%80%E8%A1%93%E3%83%8D%E3%82%BF/86/

    今回は上記の記事をなぞるだけかも。
    ほんとにやりたいのはpuppetterと連携させること。次の記事でやります。

    まず送信用メールアドレスを作る

    各レンタルサーバーでつくるがよい。
    上記はさくらの画面です。

    fs  / bluebird / co / nodemailer
    をインストールしてください。

    npm i fs
    npm i bluebird
    npm i co
    npm i nodemailer

    sendmail.js

    const co = require('co');
    const mailer = require('nodemailer');
    const fs = require('fs');
    
    const mail_config={
      "host": "xxxxxxxxxxx.ne.jp", //SMTPホスト
      "port": "587", // ポート
      "auth": {
        "user": "メールアドレス@aaa.aaaa", //ユーザー名
        "pass": "ぱすわーど" // パスワード
      }
    }
    
    //SMTPの接続
    var smtp_tmp = mailer.createTransport(mail_config);
    // プロミス化
    var smtp = require('bluebird').promisifyAll(smtp_tmp);
    
    // メール内容の設定
    var mail = {
      from: "メールアドレス@aaa.aaaa", //送信元
      to: "xxxxxxxxxxxx@gmail.com", // 送信先
      subject: "テストメール", //メールのタイトル
      text: "メール本文", //メール本文
      attachments:[{
        filename: "screenshot.png",
        content: fs.readFileSync("screenshot.png")
      }]
    };
    
    co(function*(){
      try{
        var res = yield smtp.sendMailAsync(mail);
        console.log(res);
      }catch(e){
        console.log("Error");
        console.log(e);
      }
      smtp.close();
    });
    

    同じフォルダにscreenshot.pngというファイルを置いておくと送信できます。

    実行は

    node sendmail.js
    https://logzitsu.tlog.work/pupeteer%E3%81%A7%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97%E3%81%97%E3%81%A6%E3%83%A1%E3%83%BC%E3%83%AB%E9%80%81%E4%BF%A1%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/
  • さくらインターネットサーバーでTypeSquare のWEBフォントを使う方法

    さくらサーバーではWEBフォントが使える

    さくらのレンタルサーバーではモリサワのWEBフォントが使えます。
    ただし使用には条件がありますので注意してください。

    あれ?プラグインを入れてるのに適用されてない・・・

    そういうことに気づいたのでした。
    スマホだと明朝体になってしまっている・・・・。

    原因はドメインを指定していないからでした。

    WEBフォントを使えるのは一つのドメインという決まりがあるみたいです。
    ドメインを指定するにはサーバーコントロールパネルから指定します。

    表示したいドメインを登録ドメインに指定してください。

    また、PV数が多い場合も表示されないみたいです。
    月間 25,000PV なかなかに最初は達成が難しいので、小さな規模のサイトはきにする必要はないと思います。

    WordPressの場合

    プラグインで「TypeSquare Webfonts Plugin for さくらのレンタルサーバ」を有効にして好きなフォントを選ぶだけでいいです。

    簡単ですね。
    HTMLサイトの場合も上記ページのリンクから追加方法が記載されているようですよ!

  • ラズパイ3 model B でpuppeteerを動かすまで

    いったんは諦めたのですが、しばらく放置してる間に情報がでて揃い始めてたっぽいのでせっかく買ったので有効利用したいと思います。

    ヘッドレスchromeは64bit OSでないと動かない?

    そう思って以下の記事の内容を実行しました。結論から言うと無駄だったかも。
    ubuntuが好きなので、ただのubuntu mate でよかった可能性。

    http://denor.daa.jp/raspberry-pi-3%E3%81%A764%E3%83%93%E3%83%83%E3%83%88%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E8%B5%B7%E5%8B%95-ubuntu-18-04-1-multiarch

    つまづきポイントは、viの使い方がわかんないところです。
    32bit OSの立ち上げがうまくいったあとに、windowsでconfig.txtに書き込んじゃえばいいです。
    デスクトップはいらないかもしれないけれど kubuntuとやらを入れてみました。

    Nodeのインストール

    デスクトップが立ち上がったら、何は無くともnodeのインストールです

    Ubuntuに最新のNode.jsを難なくインストールする 
    https://qiita.com/seibe/items/36cef7df85fe2cefa3ea

    上記の記事を参考にして、npmを使えるようにします。

    やっぱりpuppeteerが動かない・・・・

    結局動かなかったんですよ

    こちらの記事を参考にしました。

    https://power-of-tech.hatenablog.com/entry/2018/08/16/220252

    これでいけました。
    記事内ではバージョンを下げてますが、特に下げずに動いた上API不具合とやらもありませんでした。

    プログラムを動かす

    GCEで動かしてたプログラムが動かなくなっちゃったのでラズパイに移行しました。
    ちょっと身近になったので、ほかにもプログラムを作ってみようと思います。

  • Macで音声入力する方法

    Googleドライブで音声入力する方法や、iPhoneやAndroidで音声入力する方法が有名ですが、ちゃんとMacでもできます。

    環境設定からやってもいいんですがたまにはSiriを使ってあげてください。

    Siriの起動

    新しいモデルだと「Hei!Siri!」で動くやつもあるらしい。

    自分のはだめだったので右上のsiriマークから起動しましょう。

    「音声入力をオンにして」

    と話しかけてください。

    実際に使ってみる

    メモなど、文書入力をできる状態にして「fn」キーを2回押してください。


    拡張機能のインストールが行われることがあります。入力時にできる音声コマンドがあるみたいですね。面白いです。

    こんな感じのマークがでて音声を聞き取ってくれます。

    実はこの記事

    音声入力で作成して・・・いません!
    macbook proの新しいキーボードめちゃ快適!

  • woocommerceでメール文面を修正する

    メールの文面が不自然なので、修正する方法を調べてみました。

    文面を挿入したい場合はメールテンプレートを加工する

    設定のメール編集画面から行えますが、今回は文章の配置などはおそらく必要ないと判断したので触っていません。

    基本は翻訳ファイルを修正する

    メールの文面は翻訳ファイルに含まれています。
    まず、テストで受注メール等を試しに送ってみて、修正したい文面を翻訳ファイルないで検索して、該当箇所を修正するという形になります。

    翻訳ファイルの場所

    /wp-content/languages/plugins の中にあります。
    woocommerce-ja.mo
    woocommerce-ja.po
    をコピーしましょう。
    *後述しますが上書きするだけだとプラグインアップデート時に更新内容は消えます。

    .moが実際使われるファイル

    .moのほうが実際に使われているものですが、人間が読めない「バイナリファイル」になります。.poの方を編集し正しい内容にして、コンパイルしましょう。

    .poを.moに変換するソフト

    POEDIT
    https://poedit.net/

    このソフトでコンパイルができるみたいです。windowsでもmacでも使えそうです。
    あとは、ターミナルのコマンドでやる方法もあるみたいです。(今回は紹介しません)

    編集もこれ使った方が効率が良さそうです。
    よくみたら翻訳の提案してんじゃん!すご!
    .poを開いて編集しましょう。

     編集が終わったら上書き保存の上、ファイルメニューからMOにコンパイルして、どちらもアップロードしましょう。

    プラグインの付属ファイルなので、そのまま差し替えるとアップデートがあった時に消える。

    なので、アップデートの影響が及ばない所に保存します。
    アップロード場所は
    /wp-content/languages/woocommerce
    にフォルダを作ってアップロードしましょう。

    追記 : プラグインの元データ(.poと.mo)消さないと反映されないかも?
    消したら反映されました。

    この場合の欠点としては、アップデート時に増えた項目は英語になってしまうことです。
    Gitなどで言語ファイルを管理して、更新時に差分だけ適用するとかがいいんじゃないかと思ってます。(試してないですけど)

    メールの役割と自然な文面

    完了メールは発送通知みたいです・・・(わかりにくい)
    どんなタイミングでどのような役割のメールが届くのか、また自然な文面については以下の記事が役に立ちました。

    https://shimesan.com/2018/05/07/woocommerce-netshop-006/#i-2
  • 【結婚式に!】スライドショー動画をPremiaで作成する

    ふだん映像編集はしてないですが、adobeの契約していると普通に映像編集のソフトが使えます。
    たまーに、映像を繋げてスライドショーにして、音楽だけつけてほしいよという依頼があるので最短で編集できる方法を書き残して置きたいと思います。
    使用頻度が少なすぎて忘れちゃうんですよね。

    Adobe公式動画がめっちゃわかりやすかった。

    めっちゃ簡略的にまとまってます。
    これだけで8割OKな感じがします。

    トランジションの設定をする

    上記の編集方法に加え、画面切り替えだけ少し工夫できればいい感じです。

    画面切り替わり用語のメモ

    エフェクトパネルのエフェクトから、該当のエフェクトを探してドラッグ&ドロップする感じです。
    エフェクトの呼び名を知っておくとわかりやすいのでここにメモしておきます。

    ディゾルブ

    エフェクトパネル ビデオトランジション → ディゾルブ → クロスディゾルブ
    画面をフェードで切り替え
    シーンのはしに合わせて、「command + D」で「クロスディゾルブ」エフェクトを追加できちゃうみたいですよ。

    押し出し

    エフェクトパネル ビデオトランジション → スライド → 押し出し

    写真のサイズを動画サイズに合わせる

    フレームを選んで右クリック。フレームサイズに合わせてスケール
    するとサイズがピッタリ合います。
    複数を選択していると、一気にできます。

    動きをコピーして他のフレームに適用

    一つのフレームに拡大のエフェクトとかを自作して、他のフレームにも適用したい場合があると思います。
    コピー元のフレームを選択し、コピーします。その後コピーしたいフレームを選び、「属性をペースト」します。一気にエフェクトを適用できます。

    まとめ

    メモっとかないと忘れちゃうんで、また同じような作業しなきゃいけない時はこの記事をみながらやろうと思います。
    あと、DVDくらいの解像度なら、macbook pro 13インチの一番安いモデルでも楽々こなせそうな感じです。動画と静止画くっつけて30分ぐらいの動画になりましたが、h.264のmp4書き出しで10分というエンコード時間でした。
    実用範囲も実用範囲です。
    追記 * エンコードはやはりパワーを食う作業のようで、カクカクして真っ最中には他の作業は難しいようでした。ご注意ください。

  • Photoshopのシェイプツールの初期値がおかしくなった時の対処法

    Photoshop使ってて、シェイプの線の色が必ず赤色になってしまったり、破線や点線で書かれてしまうことがあります。
    自分の場合は、必ず 角丸が 20px 1px 1px 1px という非常に使いにくいものが毎回出てきてイライラしていたところでした。

    今回はそれの対策法です。

    ツールの初期化をする方法

    最初にツールを選択してください。

    続いて、上に出ているバーの「ツールアイコン」を右クリックします。

    ツールを初期化でOKです。全てのツールを初期化しても良いです。

  • WordPressでアキネイター作れる説(理論編)

    手動で学習させるなら、アキネイターつくれるんちゃうか、とふと思ったので実験してみる。

    アキネイターとは

    https://jp.akinator.com/

    これよ。人物を思い浮かべて質問をしていくと適切な回答を得られるというものです。
    魔法みたい。

    アキネイター仮説

    つくり方を晒してる訳ではないと思うので、推測します。
    これって実質は、「属性タグの絞り込み検索」なのではないかと思います

    質問 1で男女とか、アニメキャラか否かを分けます。

    アンパンマンを例にするとこんな感じです。
    であり、架空のキャラである。

    属性タグ説でいくとこう表現できます。

    質問によって、
    男だと判明したら、男にチェックが入る。
    架空だと判明したら架空にチェックが入る。

    そんな感じで質問によってタグ情報を追加していき、該当するものを絞り込んでいく。
    そのような仕組みなのではないかと思います。

    質問の作り方

    初期は大雑把に振り分けられる質問が多い感じがします。
    タグの数の多い質問を優先的にしていく。そんな仕組みが必要そうですね。

    事前にいい感じの質問を用意しておく必要もあります。
    この辺の仕組みはまだちょっと考え中。
    つくりながら検討します。

    機械学習と、内容の修正

    この辺はちょっとどうやったらいいか思いつきません。
    s質問の絞りこみが達成できたら考えてみようかな。

  • ブログ大改造!?記事のリライトとSEO設定の見直し!

    最近アクセス数が伸びてきた実感があるので、ブログ更新にやる気が出てきましたしのはらです。

    最初のころの方が書きたいことを書いていて、割と有用な記事も多かったと思うのですが、正直あまり伸びていません。

    アクセスが伸びやすいタイトルのつけ方を模索し始めてから、やはり反応が変わってきた感じがあるので「ちゃんとタイトルを見直そう!」と思った次第です。

    せっかく大改修をするので、そのアクセスのビフォーアフターもお届けしたいと思っています。

    ブログを書いている中で、あとでちゃんと書こう、とか後日追記しますとか、そんなことを書いている気もしますので、その辺も見直したいと思います。

    リライトって何するの?

    私もよくわかってないです(笑)

    タイトルがよくない〜ってのがいっぱいあると思うので見直します。
    それとアクセス数の集めそうな記事はdesctiption(説明文)についてもしっかり考えてみてもいいかなと思っています。

    記事の統合もいいかもしれない。

    似たような記事が複数ある場合は、統合して一つの記事にまとめてしまうのもありかもしれませんね。
    あと、カテゴリやタグについても入力をしっかりしてみるというのも試してみたいと思います。

    よくわかんねーけどとりあえずやってみよう

    ブログに意思表示すると作業が捗るってところが少なからずあるので、記事にしている節があります。
    最初から完璧なんてことはないと思うので、とりあえずやってみたいと思います!

  • Google Chrome LabsのSquoosh!とtinyPNGを比較してみた

    squoosh とは

    Google Chrome Labs の開発した画像圧縮ツールです。
    TinyPNGのようにWeb上で使うアプリです。
    PNGやJpgのほか
    webP などの新しいファイル形式にも対応しているそうです。

    早速使ってみた

    tinyPNGと同じでドラッグするだけです。ファイル形式によっては圧縮率も設定できますし、画像の劣化具合もわかりやすく比較できます。

    デフォルトの圧縮率だと劣化具合もほぼわからないので、実用的な設定になっていると思います。

    もしかして1ファイルずつしかできない・・・?これは不便ですね・・・。

    比べてみた

    圧縮率とかの設定があるので、簡単には比較できないですが・・・。

    元データ

    5.0MB

    squoosh

     mozJpg 665kb

    webP 387kb

    TinyPNG

    .jpg 602kb

    というような結果になりました。
    jpgに関してはtinyPNGのほうが小さくなりました。
    ただ、圧縮率を調整すればsquooshのほうが優れてる場合もありそうです。
    画質に関しては・・・差がわかります??
    どれも元データをアップしてあるので興味のある人は比較してみてください。

    また、新しいwebPは優れていそうですね。圧倒的に小さい。
    tinyPNGは画像を大量に処理できるのが優れているのでまだまだ使うことになりそうです。