質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

5705閲覧

【Python,スクレイピング】HPからPDFファイルを保存する方法について

yusyte

総合スコア11

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2019/06/29 10:31

前提・実現したいこと

経産省のHPから、PDFファイルを保存したい。

発生している問題・エラーメッセージ

[vagrant@localhost 20190627_scrayping_warkinggroup]$ python warkinggroup.py
Traceback (most recent call last):
File "warkinggroup.py", line 22, in <module>
urllib.request.urlretrieve(url_1, filepath)
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 188, in urlretrieve
with contextlib.closing(urlopen(url, data)) as fp:
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 163, in urlopen
return opener.open(url, data, timeout)
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 472, in open
response = meth(req, response)
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 510, in error
return self._call_chain(*args)
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 444, in _call_chain
result = func(*args)
File "/home/vagrant/.pyenv/versions/3.5.2/lib/python3.5/urllib/request.py", line 590, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

該当のソースコード

python_3.5.2

1import requests 2from bs4 import BeautifulSoup 3import urllib.request 4from urllib.parse import urljoin 5import re 6import time 7 8url = "https://www.meti.go.jp/shingikai/sankoshin/hoan_shohi/denryoku_anzen/019.html" 9base = "https://www.meti.go.jp/shingikai/sankoshin/hoan_shohi/denryoku_anzen/" 10html = requests.get(url) 11soup = BeautifulSoup(html.content, "html.parser") 12 13div = soup.find("div", class_= "main w1000") 14li = div.find_next("li") 15tags = li.find_all_next("a") 16 17for i in range(len(tags)): 18 filepath = "{}.pdf".format(i) 19 target = tags[i]["href"] 20 if re.match(r"pdf", target): 21 url_1 = urljoin(base, target) 22 urllib.request.urlretrieve(url_1, filepath) 23 # print(target) 24 # print(url_1) 25 # time.sleep(1)

試したこと

最後のurllib.request.urlretrieve(url_1, filepath)をコメントアウトとし、

print(target) # print(url_1) をアンコメントするとしっかりprintされます。

baseの絶対パス表示がおかしいのかと考え、様々試しましたがなかなかうまくいきません。
また、time関数で相手のサーバーに負荷をかけないよう配慮して行ってもいかなかったので、
やはりurllib.request.urlretrieve(url_1, filepath)の部分もしくはその変数が間違いであるんだと思います。

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

結論

以下のように書き換えることで実行できました。

python

1import requests 2from bs4 import BeautifulSoup 3import urllib.request 4from urllib.parse import urljoin 5import re 6import time 7 8url = "https://www.meti.go.jp/shingikai/sankoshin/hoan_shohi/denryoku_anzen/019.html" 9base = "https://www.meti.go.jp/shingikai/sankoshin/hoan_shohi/denryoku_anzen/" 10html = requests.get(url) 11soup = BeautifulSoup(html.content, "html.parser") 12 13div = soup.find("div", class_= "main w1000") 14li = div.find_next("li") 15tags = li.find_all_next("a") 16print(tags) 17 18headers = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"} 19 20for i in range(len(tags)): 21 filepath = "{}.pdf".format(i) 22 target = tags[i]["href"] 23 if re.match(r"pdf", target): 24 url_1 = urljoin(base, target) 25 request = urllib.request.Request(url=url_1, headers=headers) 26 with open(filepath, "wb") as f: 27 f.write(urllib.request.urlopen(request).read())

diff

diff

1 import requests 2 from bs4 import BeautifulSoup 3 import urllib.request 4 from urllib.parse import urljoin 5 import re 6 import time 7 8 url = "https://www.meti.go.jp/shingikai/sankoshin/hoan_shohi/denryoku_anzen/019.html" 9 base = "https://www.meti.go.jp/shingikai/sankoshin/hoan_shohi/denryoku_anzen/" 10 html = requests.get(url) 11 soup = BeautifulSoup(html.content, "html.parser") 12 13 div = soup.find("div", class_= "main w1000") 14 li = div.find_next("li") 15 tags = li.find_all_next("a") 16 17+ headers = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"} 18 19 for i in range(len(tags)): 20 filepath = "{}.pdf".format(i) 21 target = tags[i]["href"] 22 if re.match(r"pdf", target): 23 url_1 = urljoin(base, target) 24+ request = urllib.request.Request(url=url_1, headers=headers) 25+ with open(filepath, "wb") as f: 26+ f.write(urllib.request.urlopen(request).read()) 27- urllib.request.urlretrieve(url_1, filepath) 28- # print(target) 29- # print(url_1) 30- # time.sleep(1)

説明

リクエストの header に User-Agent が指定されていないことで403エラーが出ていました。
そこで、 header を指定するために urllib.request.urlretrieve ではなく urllib.request.urlopen を使うように変更し、開いたファイルを保存する処理を追加することで、正常に動作するようになると思います。

投稿2019/06/30 04:30

r_takahama

総合スコア106

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yusyte

2019/06/30 08:06

ご回答いただきましてありがとうございます。 ご指摘いただいた通り修正したところ、無事実行できました。 r_takahama様の解説と、https://pc.atsuhiro-me.net/entry/2013/12/04/204505を参照して、 大変理解が深まりました。 user-Agentでアクセスを制限していることがあるのですね。。勉強になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問