Puppeteerではてなブログのスターを自動でお返ししてみる

こんにちは。レモンティーです。

今回はpuppeteerではてなスターを自動でつけてみます。そんな便利なものでもないので大丈夫だとは思いますが実用はしないでください。スターに関してはスパムを禁じる規約とかが見当たらなかったのですが、あまり意味のないスパムまがいの行為ですしね…。私も今回試した以外は使いません。

puppeteerとは?

github.com
webbibouroku.com

準備

プロジェクトのディレクトリをつくりpuppeteerをインストールします。

mkdir hatena-auto-star
cd hatena-auto-star
npm init -y
npm i puppeteer

メイン部分

以下のようになります

index.js

const puppeteer = require("puppeteer");

(async () => {
    console.log("start auto add star");
    const browser = await puppeteer.launch({
        //headless:false,
        //slowMo:100
    });
    await hatenaLogin(browser,process.env.HATENA_ID,process.env.HATENA_PW);
    const targets = await makeTargetList(browser,process.env.MYBLOG_URL);
    console.log(targets);
    for(var url of targets){
        await addStarToBlog(browser,url);
    }
    console.log("finish.");
    await browser.close();
})();

launchでbrowserオブジェクトをつくり用事が終わったらcloseで閉じます。オプションのheadlessはfalseにするとGUI付きで実行されます。slowMoで動作ごとに待機させることができます。

その後、後で定義するhatenaLoginでログインしてmakeTargetListで自分のブログのうちの一つの最新の記事にスターをつけてくれた人のブログURLリストを取得します。あとはそのリストの一つ一つに対してスターをつけていきます。

このリストは別にお返しでなくても

const targets = [
  "https://www.sawalemontea.com/"
]

みたいにスターをつけたいブログのトップページのリストとかでもOKです。

ログイン

ログインの関数はこんな感じです。

index.js

async function hatenaLogin(browser,id,password){
    const page =  await browser.newPage();
    await page.goto('https://www.hatena.ne.jp/login',{waitUntil:'domcontentloaded'});
    await page.type("#login-name",id);
    await page.type("input.password",password);
    await page.click("input.submit-button");
    await page.waitForNavigation({timeout:60000,waitUntil:'domcontentloaded'});
    console.log("login");
    await page.close();
}

browser.newPageで新しいタブを開き、用事がすんだらcloseで閉じます。gotoで遷移してwaitUntilオプションに指定したイベントが起こるまで待機します。IDやパスワードの入力はtypeで行えます。そして「送信する」ボタンをclickして遷移が終わるまで待機します。

リストをつくる

ブログの最新の記事にスターをつけてくれた人のリストをつくります。

index.js

async function makeTargetList(browser,myBlogURL){
    console.log(`make list from ${myBlogURL}'s latest article`);
    const page = await browser.newPage();
    await page.goto(myBlogURL,{timeout:20000,waitUntil:'domcontentloaded'});
    //トップの記事に移動
    await Promise.all([
        page.waitForNavigation({timeout:20000,waitUntil:'load'}),
        page.click(".entry-title-link")
    ]);
    //hatena-star-star-container直下のaタグ(star)を取得
    await page.waitFor(1000);
    const stars = await page.$$('.hatena-star-star-container > a');
    //aタグからurlを取得してリスト化。ただし最初の要素はadd-star-buttonなので無視
    let urlList = [];
    for(let i=1; i<stars.length;i++){
        const star = stars[i];
        const value = await star.getProperty('href');
        const url = await value.jsonValue();
        //連続スターは1つだけ返す
        if(urlList[urlList.length-1] !== url){
            urlList.push(url);
        }
    }
    return urlList;
}

自分のブログのトップの記事に移動してpage.$$でスターのaタグを取得します。querySelectorAll的なやつです。あとはそれぞれのhrefを取り出してリストに入れて返します。

スターをつける

スターのaタグからはブログのURLが得られるのでそのブログのトップの記事に移動してスターを付けます。

index.js

async function addStarToPage(page){
    //スターをつける
    await page.click(".hatena-star-add-button").catch(err => {
        console.log(err);
        return;
    });
    //スターを付けた記事のタイトルを出力
    const titlelink = await page.$('.entry-title-link');
    const title = await titlelink.getProperty("textContent");
    const titleText = await title.jsonValue();
    console.log("add star : ",titleText);
    await page.close();
}

async function addStarToBlog(browser,blogTopURL){
    console.log("addStarToBlog url : ",blogTopURL);
    const page = await browser.newPage();
    await page.goto(blogTopURL,{timeout:20000,waitUntil:'domcontentloaded'});
    //トップの記事に移動
    await Promise.all([
        page.waitForNavigation({timeout:20000,waitUntil:'load'}),
        page.click(".entry-title-link")
    ]);
    //トップの記事にスターをつける
    await addStarToPage(page);
}

page.$はquerySelectorみたいなやつで、$$と違って最初に見つかったやつだけ返します。

実行

node index.js

で実行します。環境変数については以下

dotenvなら

npm i dotenv

して

index.js

require("dotenv").config();

.env

HATENA_ID="hoge"
HATENA_PW="huga"
MYBLOG_URL="hugo"

を追加すればできますが、共有するわけでもgit管理するわけでもないからべた書きでも同じことかも。

ファイルに書かずコマンドで指定もできます。
例えばpowershellなら

$env:HOGE="hoge"

でOKです。ターミナルを終了するまで有効です。

結果

こんな感じで出力されます。headless:falseにした場合は動く様子も見れます。

start auto add star
login
make list from https://www.sawalemontea.com/'s latest article
[ 'https://blog.hatena.ne.jp/okimusan/',
  'https://blog.hatena.ne.jp/kanahiro9-22_22-8-8/',
  'https://blog.hatena.ne.jp/tos5511/',
  'https://blog.hatena.ne.jp/mizukinoko/' ]
addStarToBlog url :  https://blog.hatena.ne.jp/okimusan/
add star :  ルアー自作プロジェクト始動します!
addStarToBlog url :  https://blog.hatena.ne.jp/kanahiro9-22_22-8-8/
add star :  4月22日は「カーペンターズの日」~カーペンターズの名前の由来は?(*´▽`*)~
addStarToBlog url :  https://blog.hatena.ne.jp/tos5511/
add star :  SSH接続の公開鍵認証でハマった話。(C# SSH.NET)
addStarToBlog url :  https://blog.hatena.ne.jp/mizukinoko/
add star :  100均のアルバイトに応募した
finish.

これ何回か試したので何個かスターがついてます。すみません。。

今回はこれでおしまいです。

www.sawalemontea.com