私のプログラミング学習は、まず実現したいことを大ざっぱにまとめ、次に書籍とウェブページから関連情報(主にコード)を探してきて、それらを組み合わせてチューニングして仕上げる、という工程になっています。
今回参照したのは次のウェブページ:
『【Python】Webスクレイピング サイトをマルッとダウンロード』
https://qiita.com/ononoy/items/c382ca698b7efe9e6119
筆者の方の説明にあるように、これは『Pythonによるスクレイピング&機械学習 開発テクニック BeautifulSoup,scikit-learn,TensorFlowを使ってみよう』(クジラ飛行机著、ソシム)という単行本を学習した記録です。この記事をまとめるまで気づかなかったのですが、実はこの本私の本棚にありました。😊
基本的に当該ウェブ記事のコードで動作するということらしいのですが、実際に2つのサイトに適用する中で2か所の修正が必要でした。
1.文字コード判定がうまくいかなくて UnicodeDecodeErrorで終了する。
⇒対処:urlretrieve の代わりに requests.get を使い、apparent_encoding で文字コードを取得する。必ずしも正確な文字コードを返してこないので、場合に応じて対処するコードを書く。以下のように修正。
def enum_links(url):
global myencoding
... 中略 ...
try:
print("download=", url)
r = requests.get(url, headers=myheader)
r.encoding = r.apparent_encoding
print("encoding =", r.encoding)
time.sleep(2)
if r.encoding == 'CP932':
myencoding = 'utf-8'
elif r.encoding == 'Windows-1254':
myencoding = 'utf-8'
else:
myencoding = 'shift_jis'
ext = os.path.splitext(savepath)[1][1:]
if ext in ['html', 'htm', 'txt', 'css', 'cgi', 'py']:
fo = open(savepath, 'w', encoding=myencoding) # テキストファイル
fo.write(r.text)
fo.close()
else:
fo = open(savepath, 'wb') # バイナリファイル
fo.write(r.content)
fo.close()
return savepath
... 後略 ...
2.リンク先がディレクトリの場合(/root/subdir/ など)、index.html の分析をしないので、その先のダウンロードがおこなわれない。ディレクトリの場合の処理を追加。修正は以下のとおり。
def analize_html(url, root_url):
global test_files
global myencoding
... 中略 ...
html = open(savepath, "r", encoding=myencoding).read()
links = enum_links(html, url)
for link_url in links:
if link_url.find(root_url) != 0:
if not re.search(r".css$", link_url): continue
if re.search(r".(html|htm)$", link_url):
analize_html(link_url, root_url)
continue
if re.search(r"/$", link_url):
analize_html(link_url, root_url)
continue
enum_links(link_url)
これで何とか、ほぼすべてのファイルをダウンロードできるようになりました。ただ、3つのhtmlファイルは想定外の文字コードのため(うち1つは encoding = None !!!)、ダウンロードに失敗しました。文字コードはやっかいです。