追記
・どっかで/entry/が抜けたらしくところどころリンクが死んでる。
・スナックエルベで過去の記事にリンクしてるのが死んでる(?)
なんかとにかくうまくいっていないようだがまーいいか(^_^;)
始まり
吾輩のブログがゴチャッてるのである*1
いつかプロを引退する日も来るであろうから少しまとめておきたい。画像はフォトライフなのでこのままでOK。
性懲りもなくTypescriptとかに挑戦しようと思ったが、サーバーサイドでやることなどない!! ので、秀丸とPythonに頑張ってもらいました。
習作
# URLを開いて記事タイトル、時間取得
# 元ページのブコメ数取得 https://bookmark.hatenaapis.com/count/entry?url=URL
# エクスポートから該当記事の先頭取得(BODY:)
# CATEGORY: はてなダイアリ時代:
# CATEGORY: はてなブログhttp時代:
# カテゴリ↑追加:秀丸で済
# 元ページのブコメが有れば https://b.hatena.ne.jp/entry/s/URL へのリンクを貼る
# 次のページがでなくなるまで繰り返す
みたいなことを最初考えてて途中まで作って、エクスポートのファイルだけで行けるわ、と方向転換
from numpy import append import requests import bs4 import json myUrl = 'https://elve.hatenadiary.com/' bUrl = 'https://bookmark.hatenaapis.com/count/entry' res = requests.get(myUrl) res.raise_for_status() soup = bs4.BeautifulSoup(res.text, 'html.parser') entries = soup.select('article') eTitles = [] eTimes = [] eUrls = [] eUrls2 = [] eBkC = [] eBkC2 = [] for e in entries: # 記事タイトル eTitles.append(e.h1.a.string) # 投稿時間 eTimes.append(e.find_all('span', { 'class': 'entry-footer-time'})[0].contents[0].contents[0].get('datetime')) # 記事URL str = e.find_all( 'span', {'class': 'entry-footer-time'})[0].contents[0].get('href') eUrls.append(str) # 記事ID部分 eUrls2.append(str[len(myUrl+'entry/'):]) # ブクマ数 param = '?url=' + \ e.find_all('span', {'class': 'entry-footer-time'} )[0].contents[0].get('href') res = json.loads(requests.get(bUrl + param).text) eBkC.append(res) param = '?url=' + \ 'http://d.hatena.ne.jp/elve/'+str[len(myUrl+'entry/'):] res = json.loads(requests.get(bUrl + param).text) eBkC2.append(res) print(eTitles) print(eTimes) print(eUrls) print(eUrls2) print(eBkC) print(eBkC2)
方向転換
ヘッダ部分のBASENAMEの文字列をhttps://snack.elve.club/entry/にくっつけたところにインポートされる。
--------
AUTHOR: elve
TITLE: No.1500 生後40年パワー
BASENAME: 2018/02/21/234751
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: 0
DATE: 02/21/2018 23:47:51
CATEGORY: 日記
CATEGORY: はてなブログhttp時代
-----
- d.hatena.ne.jp/elveをhttps://snack.elve.club/entryに置換(秀丸)
- 過去ブログ2つの記事をエクスポート
- 重複記事の抽出
- 重複記事削除
- ブクマついてたら統合前のブコメページ挿入
- いんぽーつ!
というわけで上記手順を踏んでインポートしたはずである。*2
エクスポート
設定→詳細設定のイッチャン下までスクロールして1行さらっとリンクされている。
私の場合↓なので青をはてなID、赤を対象ブログのURLにすれば行けると思われる。
https://blog.hatena.ne.jp/elve/elve.hatenadiary.jp/export/movable_type
重複記事の抽出
コレ最初に両方の出力出して比較してみたが日付めちゃくちゃでようわからんので、とりあえずだめし側の同じタイトルの記事を消すことにしました。
タイトルだけ出力すればよかったのに余計なものまで出力してます。
from numpy import append import requests import json import re bassPath = 'C:\\python\\はてな記事移行\\' myUrl = ['elveさん抜きで.txt', 'だめし.txt'] with open(bassPath + myUrl[0], encoding='utf-8') as f: lines = f.readlines() myTitles1 = [] myBaseName1 = [] myDates1 = [] for i in range(0, len(lines)): if lines[i][0:6] == 'TITLE:': myTitles1.append(lines[i][7:]) if lines[i][0:9] == 'BASENAME:': myBaseName1.append(lines[i][10:]) if lines[i][0:5] == 'DATE:': myDates1.append(lines[i][6:]) with open(bassPath + myUrl[1], encoding='utf-8') as f: lines = f.readlines() myTitles2 = [] myBaseName2 = [] myDates2 = [] for i in range(0, len(lines)): if lines[i][0:6] == 'TITLE:': myTitles2.append(lines[i][7:]) if lines[i][0:9] == 'BASENAME:': myBaseName2.append(lines[i][10:]) if lines[i][0:5] == 'DATE:': myDates2.append(lines[i][6:]) sameEntry = [] for mt1 in myTitles1: for mt2 in myTitles2: if mt1 == mt2: i = myTitles2.index(mt2) str='TITLE: '+mt2+'\tBASENAME: '+myBaseName2[i]+'\tDATE: '+myDates2[i] sameEntry.append(str.replace('\n','')+'\n') with open(bassPath + '重複情報2.txt', 'a', encoding='utf-8') as f: f.writelines(sameEntry)
重複記事削除
↑でできたファイル使って該当entry削除
from numpy import append import requests import json import re with open("C:\\python\\はてな記事移行\\だめし.txt", encoding='utf-8') as f: base = f.readlines() with open("C:\\python\\はてな記事移行\\重複情報2.txt", encoding='utf-8') as f: delen = f.readlines() def getEndEntry(i): for l in range(i,len(base)): if base[l]=='AUTHOR: elve\n': return l-1 for d in delen : tmp=d.replace('\t','\n\t') searchStr=tmp.split('\t') if searchStr[0] in base: i=base.index(searchStr[0]) s=i-1 e=getEndEntry(i) del base[s:e] with open("C:\\python\\はてな記事移行\\だめし重複削除.txt", 'w', encoding='utf-8') as f: f.writelines(base)
ブクマページ追加
# エクスポートファイルを開く # BASENAMEを読み込んでブクマがあるかチェック # 元ページのブコメ数取得 https://bookmark.hatenaapis.com/count/entry?url=URL # 有ればBODY:の下に # 以前のブクマページ[https://b.hatena.ne.jp/entry/s/URL] # を追加 from numpy import append import requests import json import re bkUrl = 'https://bookmark.hatenaapis.com/count/entry' bkCPage='https://b.hatena.ne.jp/entry/s/' bassPath = 'C:\\python\\はてな記事移行\\' myUrl = ['elveさん抜きで.txt', 'だめし重複削除.txt'] bassUrl = ['https://elve.hatenadiary.com/entry/', 'http://elve.hateblo.jp/entry/'] PageaddFlug = False for u in myUrl: with open(bassPath + u, encoding='utf-8') as f: lines = f.readlines() for i in range(0, len(lines)): if lines[i][0:9] == 'BASENAME:': # 記事URL eUrl = bassUrl[myUrl.index(u)] + lines[i][10:] # ブクマ数 param = '?url=' + eUrl.replace('\n', '') res = json.loads(requests.get(bkUrl + param).text) if res > 0: # BODYに記事追加 addFlug = True else: addFlug = False if lines[i] == "BODY:\n": if addFlug: bStr = '移動前ブクマページ: ['+ bkCPage+ re.sub('http.*//','',eUrl.replace('\n', '')) + "]\n" lines.insert(i+1, bStr) addFlug = False i = i+1 with open(bassPath + 'new_' + u, 'w', encoding='utf-8') as f: f.writelines(lines)
参考
Python 辞書(連想配列)
[解決!Python]while文やfor文で無限ループを記述するには:解決!Python - @IT
組み込み型 — Python 3.10.0b2 ドキュメント
python - BeautifulSoupを使って<li>の内容をリストとして保存する方法? - スタック・オーバーフロー
python 多次元の辞書(連想配列)の値の存在チェックをする | mebee
【Python】ファイルを開いて閉じる。open関数の使い方【入門第55回】 - narupoのブログ
【Python】ファイルを開いて閉じる。open関数の使い方【入門第55回】 - narupoのブログ
【Python】ファイルを開いて閉じる。open関数の使い方【入門第55回】 - narupoのブログ
Pythonでリスト(配列)に要素を追加するappend, extend, insert | note.nkmk.me
Pythonでリスト(配列)の要素を削除するclear, pop, remove, del | note.nkmk.me
Pythonのリストの要素のインデックス(何番目か)を取得 | note.nkmk.me
Pythonでリストのサイズ(要素数)を取得 | note.nkmk.me
Pythonで文字列を置換(replace, translate, re.sub, re.subn) | note.nkmk.me
【Python】Web APIからデータを取得する(リクエスト送信とレスポンス解析) | OFFICE54
【Python】UnicodeDecodeError: 'cp932' codec can't decodeの原因と解決方法 | OFFICE54
【Python】UnicodeDecodeError: 'cp932' codec can't decodeの原因と解決方法 | OFFICE54
Python3系の基礎文法(辞書) - Qiita
分かりやすいpythonの正規表現の例 - Qiita
Pythonの多次元Dictionary(辞書型)のキー、値の検索・存在確認 - Qiita
Pythonを利用したスクレイピング - Qiita
Pythonでlist(リスト)を検索する方法【初心者向け】現役エンジニアが解説 | TechAcademyマガジン
Pythonのgetメソッドについて現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Pythonの連想配列に要素を追加する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
pythonでimportエラーが起きる
PythonでWebページ内の特定のタグ要素をまとめて取得する
python for文を初心者向けに解説!for文基礎はこれで…|Udemy メディア
Pythonのfor文でインデックスを同時に参照する:enumerate() | UX MILK
Python | while文を使った繰り返し
Python | スライスを使って文字列の指定範囲の部分文字列を取得する
関数の定義: ゼロからのPython入門講座 - python.jp
配列・連想配列 | Python-izm
ディクショナリ | Python-izm
【Python入門】インクリメント演算子は使えない!?対処法まとめ | 侍エンジニアブログ
ファイル操作をマスターしよう!Pythonでの読み込み・書き込み方法を徹底解説! | TechTeacher Blog