プログラム関係の備忘録。技術系記事1000記事以上を目指すブログ

pythonでスクレイピング~urllib編~

  • 2021年4月15日
  • 2021年4月16日
  • python
  • 6view
  • 0件

初めに

先日からpython入門を進めている私ですが、pythonと言ったらスクレイピングや機械学習、AIといったイメージが多いかもしれません。
そこで今回は、djangoを使ったWeb開発をお休みし、超初心者向けにpythonでのスクレイピング方法をメモしていきます。

pythonでスクレイピングを行うためにはいくつか方法があるようです。

主なものは以下。

標準ライブラリ「urllib」を使う。
ライブラリ「BeautifulSoup」を使う。
ライブラリ「requests」を使う。
ライブラリ「Selenium」を使う。

それぞれ特徴があるようですが、まずは最も簡単といえるurllibを使ったWeb上のデータ取得、スクレイピングについて紹介していきます。

1.画像の保存

urlには当ブログの画像を指定し、プログラムから画像ファイルを取得し別名で保存するプログラムです。

import urllib.request


url = "https://weblion303.net/wp-content/uploads/2021/01/%E3%83%AD%E3%82%B4%E3%83%9E%E3%82%B9%E3%82%BF.png?resize=1024%2C576&ssl=1"
savename = "test.png"
mem = urllib.request.urlopen(url).read()

with open(savename, mode="wb") as f:
    f.write(mem)
print("保存OK")

結果

プログラムと同階層にファイルが保存されているのが確認できます。

解説

import urllib.request

ライブラリの読み込み。

url = "画像ファイルのパス"
savename = "保存名"

各変数

mem = urllib.request.urlopen(url).read()

関数名の通り、リソースをopenし、readで読み込みを行っています。

with open(savename, mode="wb") as f:
    f.write(mem)
print("保存OK")

ファイルを書き込み、バイナリモードで開き、writeで書き込みを行います

2-1.APIを使ったデータ取得

import urllib.request


url = "https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060"
res = urllib.request.urlopen(url).read()
text = res.decode("utf-8")
print(text)

結果

PS F:\python_prd> python download.py
{
        "message": null,
        "results": [
                {
                        "address1": "高知県",
                        "address2": "南国市",
                        "address3": "蛍が丘",
                        "kana1": "コウチケン",
                        "kana2": "ナンコクシ",
                        "kana3": "ホタルガオカ",
                        "prefcode": "39",
                        "zipcode": "7830060"
                }
        ],
        "status": 200
}

解説

# 郵便番号検索APIのURLを指定
url = "https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060"

# 画像のときと同様に、リソースを開いて読み込み
res = urllib.request.urlopen(url).read()
# 読み込んだバイナリデータを文字列に変換
text = res.decode("utf-8")
print(text)

2-2.APIを使ったデータ取得でパラメータを付与

先程は決め打ちのURLにパラメータも含めていましたが、パラメータを付けてリクエストを行いたい場合

import urllib.request as request
import urllib.parse as parse

url = "https://zipcloud.ibsnet.co.jp/api/search"

value = {
    'zipcode': '7830060' 
}
param = parse.urlencode(value)

req = url + "?" + param

res = request.urlopen(req).read()
text = res.decode("utf-8")
print(text)

結果

{
        "message": null,
        "results": [
                {
                        "address1": "高知県",
                        "address2": "南国市",
                        "address3": "蛍が丘",
                        "kana1": "コウチケン",
                        "kana2": "ナンコクシ",
                        "kana3": "ホタルガオカ",
                        "prefcode": "39",
                        "zipcode": "7830060"
                }
        ],
        "status": 200
}

解説

# 先程のパラメータ込みのURLではなくリクエストURLのみを指定
url = "https://zipcloud.ibsnet.co.jp/api/search"

# パラメータを指定し、URLエンコードを行う
value = {
    'zipcode': '7830060' 
}
param = parse.urlencode(value)

# URLを作成
req = url + "?" + param

res = request.urlopen(req).read()
text = res.decode("utf-8")
print(text)

2-3.パラメータを実行引数から指定可能にする

import sys
import urllib.request as request
import urllib.parse as parse

if len(sys.argv) <= 1:
    print("引数を指定して下さい")
    sys.exit()
number = sys.argv[1]

url = "https://zipcloud.ibsnet.co.jp/api/search"

value = {
    'zipcode': number
}
param = parse.urlencode(value)

req = url + "?" + param

res = request.urlopen(req).read()
text = res.decode("utf-8")
print(text)

結果

引数なしの時

PS F:\python_prd> python download.py        
引数を指定して下さい

引数あり

PS F:\python_prd> python download.py 0010012
{
        "message": null,
        "results": [
                {
                        "address1": "北海道",
                        "address2": "札幌市北区",
                        "address3": "北十二条西",
                        "kana1": "ホッカイドウ",
                        "kana2": "サッポロシキタク",
                        "kana3": "キタ12ジョウニシ",
                        "prefcode": "1",
                        "zipcode": "0010012"
                }
        ],
        "status": 200
}

解説

# システムのモジュールを使うために読み込み
import sys
import urllib.request as request
import urllib.parse as parse

# 実行引数がない場合、メッセージを出力し、プログラムを終了する
if len(sys.argv) <= 1:
    print("引数を指定して下さい")
    sys.exit()

# 引数から値を取得し変数に格納
number = sys.argv[1]

url = "https://zipcloud.ibsnet.co.jp/api/search"

# 先程の変数をパラメータに指定
value = {
    'zipcode': number
}
param = parse.urlencode(value)

req = url + "?" + param

res = request.urlopen(req).read()
text = res.decode("utf-8")
print(text)

最後に

これだけでも結構プログラムっぽくなりました。
郵便番号を日常的に超頻繁に検索することが多い方は「pythonで自作ツール作ってライフハックしてるぜ」と言えますね(ウソ…ではない)

今回メモしたことは多言語でも十分にできますが、より簡単で理解しやすいかなと思っています。
ただスクレイピングって言う感じではない(単にAPIで返却されるJSONを出力しているだけ)なので、次回はもう少しスクレイピングって感じの記事に続けたいと思います。