しばたテックブログ

気分で書いている技術ブログです。

はてなブログのエントリ一覧をPowerShellで取得する

小ネタです。

blog.shibata.tech

で少し触れたはてなブログのエントリ一覧を取得する方法を紹介します。

sitemap.xmlからエントリ一覧を取得する

はてなブログに限った話ではなく一般的な話として、SEO対策でクローラー向けにサイトのトップにsitemap.xmlを置いているサイトが多くあります。

はてなブログにもこのsitemap.xml*1が用意されており、以下のスクリプトでエントリの一覧を取得することができます。

$url = 'ブログのURL'
$res = Invoke-WebRequest -Uri ([IO.Path]::Combine($url, 'sitemap.xml'))
if ($res.StatusCode -ne 200) {
    return
}
# sitemapの場合
Write-Output ([xml]$res.Content).urlset.url.loc
# sitemap indexの場合
foreach ($loc in ([xml]$res.Content).sitemapindex.sitemap.loc) {
    $res2 = Invoke-WebRequest -Uri $loc
    if ($res2.StatusCode -ne 200) {
        continue
    }
    Write-Output ([xml]$res2.Content).urlset.url.loc
}

実行結果はこんな感じです。

f:id:stknohg:20180621231023p:plain

sitemap.xmlは単体でサイト内のリンクを記述している場合と、別のxmlファイルへのリンクを記述している場合があるので両者に対応しておく必要があります。
このスクリプトでは両方のケースの値を無理矢理取得しようとする単純な作りにしています。

はてなブログAtomPubを使ってエントリ一覧を取得する

はてなブログではAtom Publishing Protocol(AtomPub)によるAPIが提供されています。

このAPIを使うと、エントリの一覧や、タイトル、エントリ内容などにアクセスすることができます。
エントリの一覧を取得するには以下の様なスクリプトを実行すればOKです。

# 設定
# IDや認証情報ははてなブログの詳細設定から確認可能
$hatenaId = 'はてなID'
$blogId = 'ブログID'
$cred = Get-Credential -UserName $hatenaId

# エントリ取得(下書き含む)
$entries = & {
    function GetXmlContent ([string]$Uri, [PSCredential]$Credential) {
        $result = [PSCustomObject]@{
            Content = $null;
            NextUri = $null;
        }
        $ret = Invoke-WebRequest -Uri $Uri -Credential $Credential
        if ($ret.StatusCode -ne 200) {
            return $result
        }
        $xml = [xml]$ret.Content
        $result.Content = $xml.feed.entry
        $result.NextUri = $xml.feed.link | Where-Object rel -eq next | Select-Object -ExpandProperty href
        return $result
    }

    $result = GetXmlContent -Uri "https://blog.hatena.ne.jp/$hatenaId/$blogId/atom/entry" -Credential $cred
    Write-Output $result.Content
    while (-not [string]::IsNullOrEmpty($result.NextUri)) {
        $result = GetXmlContent -Uri $result.NextUri -Credential $cred
        Write-Output $result.Content
    }
}

# 適当に出力
$entries | ForEach-Object {
    [PSCustomObject]@{
        Title = $_.Title;
        Url = $_.link | Where-Object rel -eq alternate | Select-Object -ExpandProperty href;
        IsDraft = $_.control.draft -eq 'yes';
        #Content = $_.content.'#text';
    }
} | Format-List

実行結果はこんな感じです。

f:id:stknohg:20180621231406p:plain

このサンプルでは簡単のためにBasic認証を使用しています。
実際にスクリプトを利用する場合は自己の責任において認証方法を選択してください。

スクリプトの内容に特に目を見張るところはありませんが、ページネーションのために内部関数を用意したくらいが工夫したところでしょうか。

なお、出力形式はかなり適当なので適宜カスタマイズして利用するのがオススメです。

【補足】 Gist

当初、上記スクリプトはGistに上げていました。
補足としてリンクを記載しておきます。

*1:昔はsitemap_index.xmlだったらしい

LinuxとmacOSでPowerShell Coreのパッケージ管理方法が変わります

先日公開されたPowerShell Core 6.1.0-preview.3からLinuxとmacOSでパッケージマネージャーを使ったインストールをする際のパッケージ名に変更が入ります。

github.com

安定版とプレビュー版の分離

PowerShell Core 6.1.0-preview.2まではLinuxやmacOSのパッケージマネージャーを使う際のパッケージ名は「powershell」の一つで管理していました。
これだと安定版のみを更新していきたい人に対してプレビュー版の更新が強制されることになり非常に問題がありました。

本件に先立ってGitHubのホームにあるインストーラーのリンクが安定版とプレビュー版で分離される様になり、今回PowerShell Core 6.1.0-preview.3でパッケージ名も分離されることとなりました。

f:id:stknohg:20180615132146p:plain

(図は安定版、プレビュー版が分離されたGitHubのホーム画面)

パッケージ名の変更

ここまでを踏まえて、今後PowerShell Coreのパッケージ名は以下の様に変更されます。

  • 安定版 : powershell
  • プレビュー版 : powershell-preview

例としてapt-getの場合は以下の様に使い分けることになります。

# 安定版のインストール
sudo apt-get install -y powershell

# プレビュー版のインストール
sudo apt-get install -y powershell-preview

インストール可能なバージョン

ここから少しややこしいのですが、「OSやディストリビューションによってサポート対象となるPowerShellのバージョンが異なる」、「既にPowerShell Core 6.1.0-preview.1~preview.2をリリースしてしまっている」といった事情があるため、パッケージ毎にインストール可能なPowerShell Coreのバージョンはややこしいことになっています。

以下に現時点での一覧を記載します。

f:id:stknohg:20180615131756p:plain

これが将来的には下図の様になっていくのですが、既存のPowerShell Core 6.1.0-preview.1~preview.2がどうなるかはまだ不明です。

f:id:stknohg:20180615131837p:plain

シンボリックリンクの変更

パッケージ名の変更に合わせてPowerShell Coreの実行バイナリに対するシンボリックリンクにも変更が入ります。

たとえばUbuntuの場合、PowerShell Coreのバイナリは

  • /opt/microsoft/powershell/<バージョン番号>/pwsh

にあり、シンボリックリンクが

  • /usr/bin/pwsh

に貼られていますが、このシンボリックリンクが

  • /usr/bin/pwsh-preview

に変更されます。
安定版は/usr/bin/pwshのまま変わりません。

最後に

ざっとこんな感じです。

本来この点は最初のプレビューリリース前に考えるべき話でした。
若干対応が遅れたものの、あるべき姿に落ち着いたのは良いことだと思います。

PowerShellとSelenium WebDriver(Chrome)を使ってブログのMixed Contentをチェックする

つい先日、本ブログをホストしているはてなブログが独自ドメインのサイトに対してHTTPS対応したので本ブログをHTTPS化しました。

staff.hatenablog.com

本ブログはこれまで241エントリ公開しており、そこまで数が多くないため、今回は全エントリを目視で確認してMixed Contentがあったエントリを手動で直す対応を取りました。

Mixed Contentとなったケースは殆ど

  • 古いエントリの画像がHTTPのCDNを向いていた
  • 一部oEmbedのリンクがHTTPになっていた

であり、単純にエントリを更新しなおすことで対応できたので作業自体は非常に楽でした。
HTTPS対応とは別に古いエントリのリンク切れなども修正できたのでブログの棚卸しにちょうど良かった感じです。

本エントリの動機

当座の対応としてはこれで良かったのですが、Mixed Contentをちゃんと全滅させたか確認したくなり、これは手動ではなく機械的に全エントリをチェックすべきだろうと思ったのが本エントリの動機になります。

Mixed Contentの確認方法

私は正直WEB系の知識には疎いのですが、ざっと調べた限りMixed Contentを機械的に確認するには「それ専用のサイトやツールを利用する」「ヘッドレスブラウザを使い警告やエラーを検知する」方法がある様で、今回は後者の方法を選びました。

基本的にはこちらのブログの方式に倣っています。

こちらはPHP + Selenium WebDriver + Chromeを使い、ブラウザコンソールログからMixed Contentの警告・エラーログを検出するものとなっています。
普段PHPを使う方はこちらのブログを参考にすると良いでしょう。

私はPowerShell使いですし、ブログのネタとしても美味しいのでPowerShell + Selenium WebDriver + Chromeで同様のことをやってみることにします。

【補足】他ツール

他に

github.com

というツールも見つけました。
Nodeを使っている方であればこのツール単体でMixed Contentをチェックできます。
(実装を見る限り同じ方式を採っています。内部でpuppeteerを使っているのでサイズはそこそこ大きい様です。)

前準備

事前に以下のソフトウェアを用意しておく必要があります。

Google Chrome

www.google.co.jp

最新バージョンをインストールしておけば良いでしょう。
最低限バージョン60以降であれば全プラットフォームにおいてヘッドレスで動作させることができる様です。

今回はバージョン66を使っています。

Selenium WebDriver (C#)

こちらのダウンロードページからC#のSelenium Client & WebDriver Language Bindingsをダウンロードするか、Nugetから手動でnupkgをダウンロードしてください。
.nupkgはただのZipファイルですので、解凍して中にあるWebDriver.dllを後述するフォルダに配置します。

実行環境がWindows PowerShellの場合は、net45フォルダにあるWebDriver.dllを、PowerShell Core 6.0の場合はnetstandard2.0フォルダにあるWebDriver.dllを使います。
現時点での最新バージョンはVer.3.12です。

f:id:stknohg:20180613214317p:plain

ChromeDriver - WebDriver for Chrome

から最新バージョンのChromeDriverをダウンロードし、Zipファイルの中にあるchromedriver.exeを後述するフォルダに配置します。
現時点での最新バージョンはVer.2.40です。

PowerShellとSelenium WebDriver(Chrome)を使ってMixed Contentをチェックする

ここから本題に入ります。
今回使用するスクリプトをGistに上げました。

gist.github.com

このスクリプトを任意のフォルダに保存し、同じフォルダにWebDriver.dllchromedriver.exeを配置します。
図にするとこんな感じです。

f:id:stknohg:20180613214648p:plain

動作確認

今回はPowerShell Core 6.0(6.0.2)で動作確認してみます。
スクリプトに記載してある

はGoogleによるMixed Contentの確認用サンプルサイトです。
Chromeでアクセスすると下図の様になり、開発者ツールからコンソールログを確認するとMixed Content等の警告・エラーログが出力されていることが分かります。

f:id:stknohg:20180613231303p:plain

PowerShell Coreを起動し、このスクリプトを実行してみると下図の様にブラウザのコンソールログからMixed Contentに関するものを出力してくれます。

f:id:stknohg:20180613231742p:plain

また、接続先を変えてMixed Contentが無いサイトの場合だとこの様になります。

f:id:stknohg:20180613232128p:plain

手元の環境で試した限りではいい感じにログを出力してくれています。

ただ、ブラウザ上で見るコンソールログとSelenium WebDriverから取得するログが完全に一致しないケースがある様です。
原因は解明できていないのですが、ブラウザ上で重複してるログがSelenium WebDriverではフィルタされて取得されない様に見受けられます。
とりあえず今回の用途には問題ないだろうとの判断をしていますが、厳密なログの検証などが必要な場合は注意が要りそうです。

最後に

Selenium WebDriverのおかげで思ってた以上にお手軽にMixed Contentのチェックができました。

本エントリの例は単一のURLに対するチェックですが、スクリプトを改造して複数URLに対応するのは簡単です。
例えばはてなブログであればAtomPub APIsitemap.xmlからエントリの一覧を取得できますので、これらを組み合わせてやるとブログ全体をチェックするスクリプトも比較的容易に作成することができます。