Skip to content

Instantly share code, notes, and snippets.

@shiena
Last active April 4, 2020 21:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shiena/ccbb5f2a382cc16b616b5848594539c1 to your computer and use it in GitHub Desktop.
Save shiena/ccbb5f2a382cc16b616b5848594539c1 to your computer and use it in GitHub Desktop.
# for post article
$devToApiKey = 'your-dev.to-api-key'
# for image upload
$UserName = 'your-dev.to-username'
$Password = 'your-dev.to-password'
$seleniumHome = 'your-selenium-path'
$blackListTags = @()
# nuget install Selenium.WebDriver.ChromeDriver
# nuget install Selenium.WebDriver
# nuget install Selenium.Support
$webDriverDllPath = Convert-Path (Join-Path $seleniumHome '\Selenium.WebDriver.3.141.0\lib\netstandard2.0\WebDriver.dll')
$WebDriverSupportDllPath = Convert-Path (Join-Path $seleniumHome '\Selenium.Support.3.141.0\lib\netstandard2.0\WebDriver.Support.dll')
$chromeDriverDirPath = Convert-Path (Join-Path $seleniumHome '\Selenium.WebDriver.ChromeDriver.80.0.3987.10600\driver\win32')
if (!(Test-Path -Path $webDriverDllPath -PathType Leaf)) {
Write-Host "Not exists WebDriver.dll"
Return
}
if (!(Test-Path -Path $WebDriverSupportDllPath -PathType Leaf)) {
Write-Host "Not Exists WebDriver.Support.dll"
Return
}
if (!(Test-Path -Path $chromeDriverDirPath -PathType Container)) {
Write-Host "Not Exists chromedriver folder"
Return
}
#dll読み込み
Add-Type -Path $webDriverDllPath
Add-Type -Path $WebDriverSupportDllPath
#chrome起動
$chromeDriver = New-Object OpenQA.Selenium.Chrome.ChromeDriver($chromeDriverDirPath)
#URL開く
#dev.toのGitHub連携のサインインページを開く
$chromeDriver.Url = "https://dev.to/users/auth/github?state=navbar_basic"
#dev.toにログインする
$chromeDriver.FindElementById("login_field").SendKeys($UserName)
$chromeDriver.FindElementById("password").SendKeys($Password)
$chromeDriver.FindElementByName("commit").Submit()
#dev.toにログインするまで待つ
$webDriverWait = New-Object OpenQA.Selenium.Support.UI.WebDriverWait($chromeDriver , (New-TimeSpan -Seconds 10))
$webDriverWait.Until([OpenQA.Selenium.Support.UI.ExpectedConditions]::TitleContains("Dashboard"))
Get-ChildItem -Path . -Directory |
Select-Object @{ Label = 'item'; Expression = { $_.FullName } },
@{ Label = 'images'; Expression = { Get-ChildItem -Path $_.FullName -File -Recurse -Exclude '*.md', '*.json' } } |
Where-Object {
(Test-Path -Path (Join-Path $_.item 'meta.json') -PathType Leaf) -And
(Test-Path -Path (Join-Path $_.item 'readme.md') -PathType Leaf)
} |
Sort-Object { [DateTime](Get-Content (Join-Path $_.item 'meta.json') | ConvertFrom-Json).created_at } |
Select-Object @{
Label = 'request';
Expression = {
$meta = Get-Content (Join-Path $_.item 'meta.json') | ConvertFrom-Json
[System.Console]::WriteLine("start $($meta.title)")
$md = Get-Content (Join-Path $_.item 'readme.md') -Raw
$imageJson = @()
$_.images |
Foreach-Object {
$imagePath = $_
$imageName = (Get-Item $_).Name
#新規投稿ページに遷移する
$chromeDriver.Url = "https://dev.to/new"
$webDriverWait.Until([OpenQA.Selenium.Support.UI.ExpectedConditions]::TitleContains("New Post"))
#IMAGEボタンクリック
$chromeDriver.FindElementByXPath('//*[@id="article-form"]/form/div[1]/button').Click()
$webDriverWait.Until([OpenQA.Selenium.Support.UI.ExpectedConditions]::ElementExists([OpenQA.Selenium.By]::ClassName("articleform__overlay")))
#画像アップロード
$chromeDriver.FindElementByXPath('//*[@id="article-form"]/form/div[3]/div[1]/div[1]/input').SendKeys($imagePath)
$webDriverWait.Until([OpenQA.Selenium.Support.UI.ExpectedConditions]::ElementExists([OpenQA.Selenium.By]::Id("image-direct-copy-link-input")))
#画像のURL取得
$imageTextArea = $chromeDriver.FindElementById("image-direct-copy-link-input")
$imageLink = $imageTextArea.GetAttribute("value")
# 画像があるならアップロードしてファイル名とアップロードしたURLを対応付ける
# 画像があるならindex.mdのファイル名をアップロードしたURLに置換する
[System.Console]::WriteLine("$($imagePath) to $($imageLink)")
$imageJson += @{from = $imagePath; to = $imageLink }
$md = $md.Replace($imageName, $imageLink)
#Doneボタン
$chromeDriver.FindElementByXPath('//*[@id="article-form"]/form/div[3]/div[2]/button').Click()
$webDriverWait.Until([OpenQA.Selenium.Support.UI.ExpectedConditions]::ElementExists([OpenQA.Selenium.By]::XPath('//*[@id="article-form"]/form/div[1]/button')))
Start-Sleep 10
} |
Out-Null
if ($imageJson.Count -gt 0) {
$imageJson | ConvertTo-Json | Out-File (Join-Path $_.item 'image.json')
}
$tags = $meta.tags | Select-Object -ExpandProperty name
if ($tags.Count -gt 4) {
$tags = $tags | Where-Object { !($blackListTags.Contains($_)) }
}
$utcDate = [TimeZoneInfo]::ConvertTimeToUtc([DateTime]$meta.updated_at).ToString('yyyyMMddTHH:mmZ')
# meta.jsonからタイトル、タグ、更新日時、URLを取得
$body = @"
---
title: $($meta.title)
published: false
tags: $($tags -join ', ')
date: $($utcDate)
canonical_url: $($meta.url)
---
$($md)
"@
@{article = @{
title = $meta.title;
published = $false;
body_markdown = $body;
tags = $tags;
canonical_url = $meta.url;
}
}
}
} |
Select-Object -ExpandProperty request |
ForEach-Object {
# dev.toのAPIをキックする
$headers = @{'api-key' = $devToApiKey }
$body = [Text.Encoding]::UTF8.GetBytes(($_ | ConvertTo-Json -Compress))
$response = Invoke-RestMethod -Method Post -Uri https://dev.to/api/articles -ContentType application/json -Headers $headers -Body $body
[System.Console]::WriteLine("done $($response.url)")
Start-Sleep 5
}
#chrome終了
$chromeDriver.Quit()
$userId = 'your-user-name'
$imageFolder = "" # replace image path
$perPage = 100
(Invoke-RestMethod -Uri "https://qiita.com/api/v2/users/${userId}").items_count |
Select-Object @{label = 'pages'; expression = { 1..([Math]::Truncate($_ / $perPage) + 1) } } |
Select-Object -ExpandProperty pages |
Select-Object @{
label = 'item'
expression = {
Invoke-RestMethod -Uri "https://qiita.com/api/v2/users/${userId}/items?per_page=${perPage}&page=${_}" |
Select-Object -ExpandProperty SyncRoot |
Select-Object @{ label = 'images'; expression = {
([regex]"\((?<url>(?<parent>https://qiita-image-store\.s3\.[\w-.]*amazonaws.com/([\w-]+/)*?)(?<file>[\w-]+\.[\w]+?)?)\)").Matches($_.body) |
Select-Object @{ label = 'url'; expression = { $_.Groups["url"].Value } },
@{ label = 'parent'; expression = { $_.Groups["parent"].Value } },
@{ label = 'file'; expression = { $_.Groups["file"].Value } } |
Where-Object { -not [string]::IsNullOrEmpty($_.url) }
}
},
id, url, title, tags, body, created_at, updated_at
}
} |
Select-Object -ExpandProperty item |
ForEach-Object -Begin {
$i = 0
} -Process {
$i++
$item_folder = Join-Path "items" $_.id
$md = Join-Path $item_folder "$($_.id).md"
$indexMd = Join-Path $item_folder "readme.md"
$metaJson = Join-Path $item_folder "meta.json"
$readmeMd = Join-Path "items" "readme.md"
$existsOutputFolder = Test-Path -PathType Container $item_folder
if (-not $existsOutputFolder) {
New-Item -ItemType Directory $item_folder
}
"1. [$($_.title)]($($_.id)/readme.md)" | Out-File $readmeMd -Append:($i -gt 1)
if ($existsOutputFolder) {
Return
}
$c = ([DateTime]$_.created_at)
$u = ([DateTime]$_.updated_at)
Write-Host ("{0:yyyy-MM-dd HH-mm-ss}, {1:yyyy-MM-dd HH-mm-ss}, {2}.md, {3}, {4}" -f $c, $u, $_.id, $_.title, ($_.tags | Select-Object -ExpandProperty name | ConvertTo-Json -Compress))
$_ | Select-Object id, title, tags, url, created_at, updated_at | ConvertTo-Json | Out-File $metaJson
$_.body | Out-File $md -NoNewline
$indexBody = $_.body
$_.images |
ForEach-Object {
$indexBody = $indexBody.Replace($_.parent, $imageFolder)
}
$indexBody | Out-File $indexMd -NoNewline
$_.images | ForEach-Object {
Write-Host "`t$($_.url)"
Invoke-WebRequest -Uri $_.url -OutFile (Join-Path $item_folder $_.file)
}
}
$userId = 'your-user-name'
$pages = 1 # your-stock-pages
$imageFolder = "" # replace image path
$perPage = 100
($pages * 20) |
Select-Object @{label = 'pages'; expression = { 1..([Math]::Truncate($_ / $perPage) + 1) } } |
Select-Object -ExpandProperty pages |
Select-Object @{
label = 'item'
expression = {
Invoke-RestMethod -Uri "https://qiita.com/api/v2/users/${userId}/stocks?per_page=${perPage}&page=${_}" |
Select-Object -ExpandProperty SyncRoot |
Select-Object @{ label = 'images'; expression = {
([regex]"\((?<url>(?<parent>https://qiita-image-store\.s3\.[\w-.]*amazonaws.com/([\w-]+/)*?)(?<file>[\w-]+\.[\w]+?)?)\)").Matches($_.body) |
Select-Object @{ label = 'url'; expression = { $_.Groups["url"].Value } },
@{ label = 'parent'; expression = { $_.Groups["parent"].Value } },
@{ label = 'file'; expression = { $_.Groups["file"].Value } } |
Where-Object { -not [string]::IsNullOrEmpty($_.url) }
}
},
id, user, url, title, tags, body
}
} |
Select-Object -ExpandProperty item |
ForEach-Object -Begin {
$i = 0
} -Process {
$i++
$item_folder = Join-Path "stock" $_.id
$md = Join-Path $item_folder "$($_.id).md"
$indexMd = Join-Path $item_folder "readme.md"
$metaJson = Join-Path $item_folder "meta.json"
$readmeMd = Join-Path "stock" "readme.md"
$existsOutputFolder = Test-Path -PathType Container $item_folder
if (-not $existsOutputFolder) {
New-Item -ItemType Directory $item_folder
}
"1. [$($_.title)]($($_.id)/readme.md)" | Out-File $readmeMd -Append:($i -gt 1)
if ($existsOutputFolder) {
Return
}
Write-Host ("{0}.md, {1}, {2}" -f $_.id, $_.title, ($_.tags | Select-Object -ExpandProperty name | ConvertTo-Json -Compress))
$_ | Select-Object id, user, title, tags, url | ConvertTo-Json | Out-File $metaJson
$_.body | Out-File $md -NoNewline
$indexBody = $_.body
$_.images |
ForEach-Object {
$indexBody = $indexBody.Replace($_.parent, $imageFolder)
}
$indexBody | Out-File $indexMd -NoNewline
$_.images | ForEach-Object {
Write-Host "`t$($_.url)"
Invoke-WebRequest -Uri $_.url -OutFile (Join-Path $item_folder $_.file)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment