スローなPCライフ

がんばらないでPCの世界を楽しむつもりです。

全体表示

[ リスト | 詳細 ]

記事検索
検索

全16ページ

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

[ 次のページ ]

ブログサービス停止

 Yahoo!ブログサービスが2019/12/15でもって終了します。
 これに伴いもう一つのブログ共々、当ブログもその時点でもって消滅します。
 ブログ内の記事、コメントは退避し、PCローカル内に再構築しました。
(サービス終了スケジュール
 記事・コメントの投稿は8/31まで。一応12/15まで置いておく予定。
 場合によってはそれを待たずに削除するかも知れません。)
 
 サービス終了までに何か御用がございましたら以下にアクセス下さい。
 ブログ主へメール

開く コメント(0)

WEBスクレイピング

1) 背景
 Yahoo!ブログのサービス終了の告知があってからブログの引っ越しを考えたが、古い情報であり、特にPC関係の情報は変化が早く、誤った情報となりかねない。
 そこで他社へのブログの引っ越しは控えることにした。だが懐かしい10年におよぶ記事と写真、頂いたコメントのやり取りを残したいと思うので、全てを抜き出しローカルに保存したい。そんな動機からWEBスクレイピングに挑戦した。

 この次の機会のためにメモとして残しておく。

2) WEBページから抜き取る

 Requestsというライブラリーは指定したurlからHTMLや図表などを抜き取る為のツールである。
 Requestsの詳しい使い方はPython,Requestsの使い方 を読めば分かるが簡単な例を以下に示す。

2-1)HTML文抜き取る例
import requests
url = 'https://www.〜;' #対象にしたいサイトのurlを指定
r = request.get(url)
enc = r.encoding #encodingを得る 
htmls = r.text #html文を取り出す
for hrml in htmls:
print(html) #取り出したHTML文を表示する

2-2)画像をダウンロードする例
url_image = 'https://www.〜;' #対象画像のあるurlを指定
r_image = requests.get(url_image)
img_type = r_image.headers['Content-Type']) # image/png
filename_image = os.path.basename(url_image)
with open(filename_image, 'wb') as f: # 画像ファイルを保存する。
f.write(r_image.content)

3) HTMLを分析する

 HTML.ParserはRequests等で抜き出したHTMLの構文解析をする為のライブラリで、これにより、HTML文中から必要なデータを見つけ出すことが出来る。
 試してみればとてもシンプルな使い方であることが理解できる。
参考資料:
3-1)HTMLParserの使い方
 まず大まかな使い方の流れを見ると、
3-1-1 ライブラリのimportする。
from html.parser import HTMLParser

3-1-2 HTMLParserを継承した目的に合ったのクラスを準備する。
 class MyHTMLParser(HTMLParser): # MyHTMLParserというクラスを作る。

 このクラスの中に次のメソッドを4つ書くことになるのだが。
 __init__
 handle_startag
 handle_endtag
 handle_data
 すなわち元々備わっている4つのメソッドを上書きし、目的に合った処理をさせる訳である。

3-1-3 HTMLの構文解析を実施
 parser = MyHTMLParser() # MyHTMLParserのインスタンスを作る。
parser.feed(html文) # requestsで取ってきたHTML文を渡す。
parser.close()
結果=parser.list(self) # 結果を受け取る。

 feed(html文)でHTML文を取込み、一行ずつ分析する際に4つのメソッドが使われ、全ての行の解析が行われる。
 
3-2)4つのメソッドについて
 HTMLはブロクの集まりで構成され、ブロックの中にまた別のブロックが含まれているという階層構造になっている。それぞれのブロックは開始タグと終了タグで囲まれる形となっている。このタグで挟まれた中にデータがあり、必要なデータがどのタグで構成されたブロックにあるかを調べることによって取り出すことができる。
 尚、開始タグ中の属性の値として必要なデータがある場合もある。

 次にブログのHTMLファイルの一部分を載せ、ブログの書庫名である「サイクリング」、「リカンベント」、自転車関係」の文字列とそれぞれの場所をあらわすurlを取り出す例を載せる。
イメージ 1

 この例のHTMLを見ればaタグがターゲットになるタグだとわかる。
 しかし、aタグはHTMLファイルのここに載っていない部分にも多数存在し、それらは対象にしたくない。それでその対象を絞り込むのがhandle_startagメソッドの主要な役割となる。と同時にターゲットのタグの中に要素の値を持っている場合は、ここでそれを取り出すこともしなくてはならない。

3-2-1、handle_startagメソッド

def handle_starttag(self, tag, attrs):
attrs = dict(attrs) #タプルを辞書にする
if tag == 'ul' and 'class' in attrs:
if attrs['class'] == 'libraryList':
 self.ul = True
if tag == 'a' and self.ul:
self.a=True
self.libl.append([attrs['href']])
self.i = self.i + 1

 このメソッドは利用される時に開始タグと、属性の集まりを引数として受け取っている。
 なお、受け取るタグと属性の文字は小文字に変換されている。
 受け取った属性はタプルになっているが、これを一旦辞書の形に置き換えたほうが扱いやすい。
 この例では'libraryList'という属性値をもつulタグであればself.ulという変数をTrueにして、ulタグの中に入ったことを分かるようにしている。
 aタグを見つけたなら、それがulタグの中にあれば、aタグの中に入ったことを分かるようにself.aをTrueにしている。
 同時にaタグの属性値がurlなので、これを取り出してself.liblに追加する。
 実はself.liblという変数項目に結果を集めようとしている。

3-2-2、__init__メソッド
 
 説明の順番が逆になってしまったがhandle_starttagメソッドで使われるインスタンス変数self.ul、self.a、self.libl、self.iをここでFalseに初期化している。

def __init__(self):
HTMLParser.__init__(self)
self.ul = False
self.a= False
self.libl = []
self.i = -1

3-2-3、handle_endtagメソッド

def handle_endtag(self, tag):
if tag == 'ul' :
self.ul = False
if tag == 'a' :
self.a = False

 handle_starttagではself.ul、self.aをTrueにしているが、終了タグを確認したのでそれらをFalseにしてブロックから抜けたことが分かるようにしなければならない。このメソッドではそれを行うだけ。

3-2-4、handle_dataメソッド

 ここではself.aがTrueであれば、dataにはaタグのブロックの値が入っているはずなので、これをself.liblに追加する。
 ちょっとわかり難いが今回例ではself.liblは
 [['https:・・・23683.jtml', 'サイクリング'],['https:・・・282014.html', 'リカンベント'],['https:・・・1037901.html', '自転車関係']]となる。

def handle_data(self, data):
if self.a :
self.libl[self.i].append(data) 

3-2-5、結果の取り出しメソッド
def list(self):
return self.libl

 このメソッドは私が付け加えた解析結果を取り出すためのメソッド

 以上は書庫の一覧を取り出すためのクラスを例にしたが、記事を取り出すためにはまた別に記事の構造に合わせたクラスを用意した。

 4つのメソッドはやっていることが単純なので、覚えることが少なくてわかりやすいと思う。
 初めは戸惑ったが、実際に始めたら簡単にできた。
 今回、WEBスクレイピングをしてみて何が大変だっかと言えば、対象となるHTMLの構造を調べることだった。
 構造を知らなければどういう条件でタグを絞り込めばよいのかわからない。
 ブログの記事そのものは数行しか無くても、PCやスマートフォン、その他いろいろな環境でも使いやすくするために考えられているので1200行くらいのボリュームとなっていた。この大量の行の中から必要なデータがどこにあるのかを探すだけでも手間が掛かった。
 また、人間が見て階層構造がわかるような書き方になっていないので、開始タグ、終了タグの対応関係を確認するのも手間が掛かった。準備には時間がかかったが、抜き出しは20数分で速やかに終わった。人手で抜き出していたら大変な時間になっただろうしミスも犯すだろう。スクレイピングできて良かった。

 なお、抜き出した文字データと写真を使ってローカル(PC内)に再構築を別途進めている。

開く コメント(0)

開く トラックバック(0)

ブログ抜き出しテスト

 Yahooブログからの抜き出しプログラムのテスト実行をしています。
 プログラムはサーバーに負荷をかけないよう1秒以上続けてアクセスしないようにしています。
 1サイクルを[サーバーへのアクセス + PC側での処理]として時間計測し、0.5秒以内ならもう1サイクル実行するという形にしています。
 記事1件文の吐き出し部分をパスすれば0.5秒内に4〜5サイクル可能ですが、記事の書き出しを含むと精々1件しか出来ませんでした。
 0.6秒に設定すると条件が良ければ2サイクル行けるみたいです。
 今は0.6秒を越えたら1.2秒休むという形で、件数で割り算すると1件あたり2秒位になります。

 抜き出したデータを細かく調べて不具合と原因を洗い出しています。
 本文が全く抜けてない記事と途中で途切れる記事がありました。その原因は次の3項目。
1)記事の投稿方法によりHTMLの構造に違いがある。
 構造が違うので抜き取れない場合がある。自分が使う方法にだけは対応した。
2)本文中にタブ文字を使うとインデントに関するタグが挿入される。
 このタグに対応出来てなかったのを対応させたが、再現時に問題がでるかも。タブの再現に注意
3)WiKi文法にミスがあった場合に、予期していたHTMLタグが作られてない。
 画像貼り付けの文で"center"のスペルミスをしていた例があった。
 リンク指定でurl部分と表示部分との区切りを間違って全角空白にしていた例があった。
 プログラムをなおすよもブログ側で直すのがベター。
 これらはブログ上で記事を注意深くチェックすれば気づけるので、本番実行までに確認しておきたい。

 他にも不具合がないかチェックを続けます。書庫間の記事の移動も、あれば8/31までに検討。

開く コメント(0)

 先の記事で、ブログの移行をするか終了か決め兼ねていると書きましたが、ようやく決めました。
○元ブログの既存の記事については移行はしないことにしました。
 移行しない大きな理由は、
・既に過去の話となっていること。
・分野によっては情報が古いことは迷惑でもあること。
・既存の記事と画像については抜き取っるプログラムの目処がたった。
(コメントも抜くか諦めるか、これから検討)
(後は出力の仕方で悩んでいる。少し検討に時間が掛かりそう。)

 過去分についてはHDD内に持ち、ブラウザで見えるようにするつもり。

○新たなブログ開設は、落ち着いて検討したいと思います。
 新設先をどこにするかというのも課題として残っています。

開く コメント(0)

 このブログはまだ2年弱ですが、もうひとつのブログは10年強になります。長い間、お世話になりました。
 まだ移行するか終了するか決め兼ねています。移行する場合は移行先も決めねばなりませんね

 移行する場合はYahoo側から4社についての移行ツールが用意されるとのことですが、その他にはFC2に引っ越しツールもあるようです。

 終了させる場合は、記事をPCローカルにブラウザで見える形で残したいところです。
 バックアップツールは提供されないので、「無ければ作る」精神で自助努力してみます。
 数画面ほどYahoo!ブログのHTMLソースを抜き出して構造を調べ始めました。小さな記事のファイルでも膨大な量のHTML文が付いています。必要な情報がどこにあるかを探すのにひと苦労してます。
 必要なPythonのライブラリの使い方を学びながらのプログラミングになるので出来るか不安。

 
 

開く コメント(0)

全16ページ

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

[ 次のページ ]


.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事