スクリプト置き場
Page last edited 1,533 日前
提供:新型コロナ総合Wiki
Jump to navigation
Jump to search
魚拓作成用ブックマークレット[編集 | ソースを編集]
1 javascript:(function() { var url = location.href; var URLs =["http://web.archive.org/save/","https://archive.ph/?run=1&url=","http://megalodon.jp/?url="]; for( var i in URLs){ var redirect_url = URLs[i] + url ; window.open(redirect_url, "_blank"); };})()
時事通信のニュースのリンクをmedia wiki形式に書き換えるスクリプト(python3.8)[編集 | ソースを編集]
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 """
5 このスクリプトはPython3.7以上で動くはずです。
6 共同通信のニュースのURLからタイトルと日付を取出しMediaWiki形式でテキストに保存します
7 テキストの保存例は次のようになっています
8
9 ====year/month/day1====
10 *[記事1のURL 記事のタイトル1]
11 *[記事2のURL 記事のタイトル2]
12 ︙
13 ====year/month/day2====
14 *[記事3のURL 記事のタイトル3]
15 ︙
16
17
18 文字コードがUTF-8で保存された1行に1URLあるテキストファイルから、URL先にアクセスしタイトルと日付を取出し指定した名前でutf-8で保存します.
19
20 使い方:
21 hoge
22 ├── このpythonファイル.py
23 └── urlリスト.txt
24 のとき
25
26 $ このpythonファイル.py ["urlリスト.txt"] ["出力するファイル名.txt"]
27
28 と入力するとurlリスト.txtが以下のようにそのディレクトリに出力されます。
29
30 hoge
31 ├── このpythonファイル.py
32 ├── 出力するファイル名.txt
33 └── urlリスト.txt
34
35
36
37 """
38 import datetime
39 import itertools
40 import sys
41
42 import pytz
43 import requests
44 from bs4 import BeautifulSoup
45
46
47 def main(url_list_name: str = "urltext.txt", output_filename: str = "共同通信wiki用記事と日付.txt"):
48 article_info_list = []
49 url_list = import_url_lists(url_list_name)
50
51 for url in url_list:
52 content = get_url_content(url) # httpでgetリクエストを送る
53 article_info = scrap_article_information(content, url) # bs4で記事から時刻とタイトルを取得
54 article_info["url"] = url
55 article_info_list.append(article_info)
56
57 article_info_list.sort(key=lambda x: x["time"]) # 時刻順にソート
58 wiki_data = change_to_media_wiki_format(article_info_list) # 取得したデータをmedia wiki形式に変換
59 save_to_text(wiki_data, output_filename) # media wiki形式に変換したデータをテキストに保存
60 # print(output_filename)
61 # print(url_list)
62 # print(article_info_list)
63
64
65 def import_url_lists(path_text):
66 """テキストファイルからURLを取得
67 空白行は除去されるがテクストがURLかどうかは判断しない
68 """
69 with open(path_text, "r") as f:
70 lines: list = f.read().splitlines()
71 lines = [a for a in lines if a != ''] # 空白行除去
72 return lines
73
74
75 def get_url_content(url: str):
76 """
77 URLからHTMLを取得する
78 HTTPステータスコードに問題があった場合処理を終了し標準出力にエラーコードなどを返す
79 :param url:strのURLが入るようにしてください
80 :return:
81 """
82 r = requests.get(url)
83
84 if not r.status_code == 200: # 接続が正常化か確認し、正常でなければプログラムを終了する
85 print("インターネットの接続に問題があります。HTTPステータスコード{err_code}\n "
86 "最後に読み込んでいたURLは\n {loaded_url}"
87 .format(err_code=r.status_code, loaded_url=url))
88 sys.exit(1) # プロセスを終了
89
90 return r.content
91
92
93 def scrap_article_information(r: bytes,
94 url: str = "URLがscrap_article_information関数に渡されていません") -> dict:
95 """
96 記事から記事のタイトルと時間を取得します
97 :type url:スクレピングしているurl。主にエラー発生時にどのURLでエラーが発生しているか調べるためのもの。省略可能
98 :param r:requests.get(url)で取得したものが入るようにしてください
99 :return:
100 """
101 soup = BeautifulSoup(r)
102
103 if soup.find("title") is None: # 記事の見出しの読み込み確認
104 print("記事のタイトルが読み込みできませんでした\n正しく記事を読みこめていますか?\n" +
105 "一度ブラウザで\n{url}\nを開き確認してみてください".format(url=url))
106 sys.exit(1)
107 article_tittle = soup.find("title").string
108
109 if soup.find("time") is None: # 時刻の読み込み確認
110 print("記事の時刻が読み込みできませんでした\n正しく記事を読みこめていますか?\n" +
111 "一度ブラウザで\n{url}\nを開き確認してみてください".format(url=url))
112 sys.exit(1)
113 time_string = soup.find("time", class_="main__date").contents[0]
114
115 article_time = change_str_to_date_type(time_string) # 文字列を時刻に型変換
116 article_dict = {"title": article_tittle, "time": article_time}
117 return article_dict
118
119
120 def change_str_to_date_type(article_time: str) -> datetime:
121 """
122 2017/4/8 03:05 (JST)といった月と日付が0埋めされていない文字列なので
123 Mac,Linuxでは%-m, %-dなどで動くがwindowsだとC言語の実装の影響で動かない
124 OS互換性のために仕方が無いので文字列を年,月,日付,時刻,タイムゾーンに分解して処理
125 """
126 article_date_time = [int(s) if len(s) == 1 else int(s) for s in article_time.split(" ")[0].split("/")] + \
127 [int(s) for s in article_time.split(" ")[1].split(":")] # 日付と時刻を読み込みやすい威容に整形
128 tz: datetime = None
129 if "JST" in article_time.split(" ")[1]: # 文字列がJSTならばタイムジーンを東京に変更
130 tz = pytz.timezone('Asia/Tokyo')
131
132 article_time = datetime.datetime(*article_date_time, tzinfo=tz)
133 return article_time
134
135
136 def change_to_media_wiki_format(data_wiki: list) -> str:
137 """
138 スクレピングしてきたデータをmedia wiki形式に変換する関数
139 :param data_wiki:
140 data_wikiの構造は予め時刻でソートされているリストを期待していて
141 [{"title":記事のタイトル, "time": 記事の時刻データ(タイムゾーンあり),"url":記事のurl},
142 ︙
143 {"title":記事のタイトル, "time": 記事の時刻データ(タイムゾーンあり),"url":記事のurl}]
144 という風になっていることが前提
145
146 :return:
147 """
148 out_text = "" # type:str
149 for key, group in itertools.groupby(data_wiki, key=lambda m: m['time'].strftime("%Y/%m/%d/")): # 日付でリストをグループ分け
150
151 out_text += ("===={0}====\n".format(key)) # key(日付データをテキストに書き込み)
152
153 for data_wiki in group: # 記事のタイトルとURLをwiki形式に変換しテキストに書き込み
154 title = data_wiki["title"].split("\u3000")[0].split(" | ")[0]
155 try: # 副見出しがある時だけ追加 ないときはIndexErrorが返ってくるので無視
156 title += " " + data_wiki["title"].split("\u3000")[1].split(" | ")[0]
157 except IndexError:
158 pass
159
160 url = data_wiki["url"]
161 link = "*[{url} {title}]\n".format(url=url, title=title)
162 out_text += link
163 return out_text
164
165
166 def save_to_text(wiki_data: str, name: str):
167 with open(name, "w", encoding="utf-8") as f:
168 f.write(wiki_data)
169 print("{name}として保存しました".format(name=name))
170
171
172 if __name__ == "__main__":
173 url_list_file_path = sys.argv[1]
174 out_text_name: str = sys.argv[2]
175 main(url_list_file_path, out_text_name)