表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
13/13

最後に

 さて、ずいぶん放置してしまったこちらの話ですが、ここではスナップショットとしてのデータを参照する方法を述べてきました。

 その後もデータを貯め続けていたのですが、昨年の9月から10月にかけて、一時フォルダを削除してしまったためにデータを取れなくなってしまっていました。その後、再開時にスクリプトを修正し、メモリの使用を減らすことにしました。結局のところ、JSONをオンラインで使用するのは諦めて、ファイルとして追記する形に変更したところ、実行時間も短く動作は大幅に安定することになりました。


 こうして貯めたデータは、今はDBに取り込んで、時系列に沿った解析なども出来るようにしてみてあります。ですので、スナップショットを解析する、という形でのこの項は、最後に更新したスクリプトを掲載してクローズすることにします。


 このデータを使って、過去データの解析をしているエッセイを、もし目にされることがありましたら、笑ってごらんになっていただけると幸いです。


以下、更新したスクリプト

-------

# なろうAPIのベースurl

$apiBase = "https://api.syosetu.com/novelapi/api/?out=json"


# 出力ディレクトリ

$outputBase = 'g:\narou'


# DateTimeOffsetをUnix epoch秒に変換する

function ToEpoch {

Param (

[DateTimeOffset] $dt

)


return $dt.ToUnixTimeSeconds()

}


# サンプル開始日時(JST)

$from = ToEpoch "2004/5/1"

#$from = ToEpoch "2022/7/1"


# 重複取得をチェックするためのハッシュ

$checker = @{}


# gzipの展開関数

# https://social.technet.microsoft.com/Forums/windowsserver/en-US/5aa53fef-5229-4313-a035-8b3a38ab93f5/unzip-gz-files-using-powershell?forum=winserverpowershell

Function DeGZip-File{

Param(

$infile

)

$input = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)

$output = New-Object System.IO.MemoryStream

$gzipStream = New-Object System.IO.Compression.GzipStream $input, ([IO.Compression.CompressionMode]::Decompress)

$buffer = New-Object byte[](1024)

while($true){

$read = $gzipstream.Read($buffer, 0, 1024)

if ($read -le 0){break}

$output.Write($buffer, 0, $read)

}

$gzipStream.Close()

$input.Close()


$dummy = $output.Seek(0, [System.IO.SeekOrigin]::Begin)

$reader = New-Object System.IO.StreamReader $output


return $reader.ReadToEnd()

}


# 一定範囲のデータ取得

function GetData(

[long] $from,

[long] $to,

[string] $base,

[System.Collections.ArrayList] $result,

[int] $count

){


$current = 1


while ($current -lt $count) {

try {

$res = Invoke-WebRequest ($apiBase + "&lim=500&gzip=5&st=" + $current + "&lastup=" + $from + "-" + $to) -OutFile "c:/temp/narou.tmp.gz"


$global:fileSize += (Get-Item c:\temp\narou.tmp.gz).Length

#Write-Output $global:fileSize


$content = DeGZip-File "c:/temp/narou.tmp.gz"

$json = ConvertFrom-Json $content


for ($i = 1; $i -lt $json.Count; $i++) {

$ncode = $json[$i].ncode

if ($checker[$ncode] -eq $Null) {

$dummy = $result.Add($json[$i])

$checker[$ncode] = $True

}

else {

Write-Output "Duplicate:" + ncode

}

}


if ($json.Count -eq 1) {

Write-Output "Short Data"

break

}


$current += $json.Count - 1

}

catch {

$r = $_.Exception.Response

$rs = $r.GetResponseStream()

$rs.Position = 0

$sr = [System.IO.StreamReader]::new($rs)

$res = $sr.ReadToEnd()

$sr.Close()


Write-Error $res


Start-Sleep 60

}

}

}


# 一定範囲のデータ件数取得

function GetCount(

[Long] $from,

[Long] $to,

[String] $base

){


$url = $base + "&lastup=" + $from + "-" + $to + "&lim=1"

while ($true) {

try {

$result = Invoke-WebRequest $url

$json = ConvertFrom-Json $result.Content


return $json[0].allcount

}

catch {

Write-Error $_


$r = $_.Exception.Response

$rs = $r.GetResponseStream()

$rs.Position = 0

$sr = [System.IO.StreamReader]::new($rs)

$res = $sr.ReadToEnd()

$sr.Close()


Write-Error $res


Start-Sleep 6000

}

}

}


# 取得件数が500-2000件となるように、ウィンドウを調整する

function GetLimit(

[Long] $start,

[String] $base,

[Long] $step

){


$count = GetCount $start ($start + $step) $base

while ($count -le 500) {

$step *= 2

$count = GetCount $start ($start + $step) $base

}


while ($count -ge 2000) {

$step /= 2

$count = GetCount $start ($start + $step) $base

}


return $count, $step

}


# 取得データを保存する変数

$result = New-Object System.Collections.ArrayList


# ダウンロードしたデータ長

$global:fileSize = 0


# ウィンドウ変数

$now = [DateTimeOffset]::Now

$limit = ToEpoch $now

$step = $limit - $from


# JSONの出力

# FilePathの引数がJSONの出力ファイル名

$targetJson = $outputBase + '\narou.json'

$targetZip = $outputBase + '\narou.' + (Get-Date -Format "yyyyMMdd") + ".zip"


Out-File -FilePath $targetJson -Force -InputObject "["


# サンプルを開始する

$first = $true

while ($from -lt $limit) {

$fromStr = ([DateTimeOffset]::FromUnixTimeSeconds($from).ToString())


Write-Output $fromStr


$temp = GetLimit $from $apiBase $step

$count = $temp[0]

$step = $temp[1]


GetData $from ($from + $step) $apiBase $result $count


$from += $step + 1


if ($first) {

$first = $false

$prefix = ""

}

else {

$prefix = ","

}


$str = ConvertTo-Json -Compress -InputObject $result

$str = $prefix + $str.Substring(1, $str.Length - 2)


OUt-File -FilePath $targetJson -Append -InputObject $str

$result = New-Object System.Collections.ArrayList

}


Out-File -FilePath $targetJson -Append -InputObject "]"


##ConvertTo-Json -Compress $result | Out-File -FilePath $targetJson -Force

# 以下は、日付別のzipに固めるためのもの

Compress-Archive -DestinationPath $targetZip -Path $targetJson


Write-Output ("All Done, Transfer Size:" + $global:fileSize)


評価をするにはログインしてください。
この作品をシェア
Twitter LINEで送る
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

この作品はリンクフリーです。ご自由にリンク(紹介)してください。
この作品はスマートフォン対応です。スマートフォンかパソコンかを自動で判別し、適切なページを表示します。

↑ページトップへ