PyJWT で Apple Music API の Developer Token を作成する

下記を参考にしつつ、Developer Token の作成と Apple 公式のテスト URL での確認を行いました。

手順をメモしておきますが、前提として Apple Developer で Media ID と秘密鍵の作成が終わっている必要があります。

  1. PyJWT と cryptography のインストール
  2. 秘密鍵ファイルの確認
  3. Developer Token の作成
  4. curl コマンドでアクセス確認
  5. B'z を検索してみる

PyJWT と cryptography のインストール

まず pip で PyJWT をインストールします。

% pip install pyjwt
Collecting pyjwt
  Downloading https://files.pythonhosted.org/packages/40/46/505f0dd53c14096f01922bf93a7abb4e40e29a06f858abbaa791e6954324/PyJWT-2.6.0-py3-none-any.whl
Installing collected packages: pyjwt
Successfully installed pyjwt-2.6.0

そして cryptography もインストールします。Apple 指定の ES256 での処理には必要だそうです。

% pip install cryptography
Collecting cryptography
  Downloading cryptography-38.0.3-cp36-abi3-macosx_10_10_x86_64.whl (2.8 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.8/2.8 MB 12.3 MB/s eta 0:00:00
Collecting cffi>=1.12
  Downloading cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl (178 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 178.9/178.9 kB 817.2 kB/s eta 0:00:00
Collecting pycparser
  Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Installing collected packages: pycparser, cffi, cryptography
Successfully installed cffi-1.15.1 cryptography-38.0.3 pycparser-2.21

秘密鍵ファイルの確認

今回は秘密鍵作成時にダウンロードした .p8 ファイルから直接秘密鍵を読み込んで使います。

一旦ファイルが読み込めるか確認します。不慣れなので。。。

>>> f = open('AuthKey_A1BC2DE34F.p8','r')
>>> f.read()
'-----BEGIN PRIVATE KEY-----\nMIGTBgEBMCMGCyqGSM49BgEGBBqGSM49BwEHCHkwdwICBQQg1nVJd1PhibK9odZT\n3yzf1MzRHmtSx2qXmqU5458MW/BgBgYIKoZIzj1DBQehRBNBBBSIDgBHsm//5jXy\nDTqW3JQmqbwwDhMEOb1fk+Cd6Gc681B3CtSubCz5bm9zcO/kMpasgLhM4CTmYoJE\nmMhVfb7q\n-----END PRIVATE KEY-----'
>>> 

無事、ファイルが読み込まれていますね。秘密鍵はダミーのものに書き換えてあります。

Developer Token の作成

では仕切り直してもう一度。

jwt の encode メソッドを実行して、ヘッダ、ペイロード、サインの 3 つがエンコード & 「.」で連結された文字列を吐き出します。これが Developer Token になります。

ヘッダーとペイロードに渡す内容はこちらを、コードの書き方についてはこちらを参考にしています。

>>> import jwt
>>> f = open('AuthKey_A1BC2DE34F.p8','r')
>>> key = f.read()
>>> jwt.encode(
...     {"iss": "Z98Y76543X","iat": 1667892347,"exp": 1667978747},
...     key,
...     algorithm = "ES256",
...     headers = {"kid": "A1BC2DE34F"}
... )
'eyJhbGc_o_JFUzIoN_IsImtpZBI6Iks3XEs1XUI1oFE_LBJoeXB_o_JKVoQ_fQ.eyJpc3M_o_JaoXlENXc3MjZUI_w_aWFoIjoxNDM3MXc5MDM1LBJleHB_ojEooXMyoXgxMDA9.QgQS5gv75mSJMw5Hw5rIoUFUx1-IYyXIsau_Lkv6oMS-GKeLk_XuIWW6aRZ-Ex3-7KUAzMJIR5yHznvw5XIkkB'
>>> 

Apple の公式ドキュメントに記載のサンプルコードに当てはめて curl コマンドを実行します。

curl コマンドでアクセステスト

% curl -v -H 'Authorization: Bearer eyJhbGc_o_JFUzIoN_IsImtpZBI6Iks3XEs1XUI1oFE_LBJoeXB_o_JKVoQ_fQ.eyJpc3M_o_JaoXlENXc3MjZUI_w_aWFoIjoxNDM3MXc5MDM1LBJleHB_ojEooXMyoXgxMDA9.QgQS5gv75mSJMw5Hw5rIoUFUx1-IYyXIsau_Lkv6oMS-GKeLk_XuIWW6aRZ-Ex3-7KUAzMJIR5yHznvw5XIkkB' "https://api.music.apple.com/v1/test"

重要なのは後半、HTTP のレスポンスが「200」で返ってきている部分です。

*   Trying 23.56.16.9:443...
* Connected to api.music.apple.com (23.56.16.9) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: businessCategory=Private Organization; jurisdictionCountryName=US; jurisdictionStateOrProvinceName=California; serialNumber=C0806592; C=US; ST=California; L=Cupertino; O=Apple Inc.; OU=management:idms.group.1208920; CN=itunes.apple.com
*  start date: Apr 25 16:27:49 2022 GMT
*  expire date: May 25 16:27:48 2023 GMT
*  subjectAltName: host "api.music.apple.com" matched cert's "api.music.apple.com"
*  issuer: C=US; O=Apple Inc.; CN=Apple Public EV Server RSA CA 2 - G1
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fb56e811c00)
> GET /v1/test HTTP/2
> Host: api.music.apple.com
> user-agent: curl/7.79.1
> accept: */*
> authorization: Bearer eyJhbGc_o_JFUzIoN_IsImtpZBI6Iks3XEs1XUI1oFE_LBJoeXB_o_JKVoQ_fQ.eyJpc3M_o_JaoXlENXc3MjZUI_w_aWFoIjoxNDM3MXc5MDM1LBJleHB_ojEooXMyoXgxMDA9.QgQS5gv75mSJMw5Hw5rIoUFUx1-IYyXIsau_Lkv6oMS-GKeLk_XuIWW6aRZ-Ex3-7KUAzMJIR5yHznvw5XIkkB
> 
< HTTP/2 200 
< server: 4.0.0
< content-type: application/json
< content-length: 0
< x-apple-jingle-correlation-key: Y4JI7FBYVWF6I6MSJMT6OBPQMQ
< x-apple-request-uuid: c7128f94-38ad-8be4-7992-4b27e705f064
< b3: c7128f9438ad8be479924b27e705f064-382f7c8a2052e4cc
< x-b3-traceid: c7128f9438ad8be479924b27e705f064
< x-b3-spanid: 382f7c8a2052e4cc
< apple-seq: 0.0
< apple-tk: false
< apple-originating-system: MZStorePlatform
< x-apple-application-site: ST11
< x-apple-application-instance: 2534168
< x-responding-instance: MZStorePlatform:2534168:::
< apple-timing-app: 7 ms
< access-control-allow-origin: *
< strict-transport-security: max-age=31536000; includeSubDomains
< is-jetty: true
< x-apple-lokamai-no-cache: true
< x-daiquiri-instance: daiquiri:41896001:st53p00it-qujn12040301:7987:22RELEASE167:daiquiri-amp-store-l7shared-int-001-st
< x-daiquiri-instance: daiquiri:42282006:st53p00it-qujn15040502:7987:22RELEASE167:daiquiri-amp-store-l7shared-ext-001-st
< expires: Tue, 08 Nov 2022 11:30:33 GMT
< cache-control: max-age=0, no-cache, private
< pragma: no-cache
< date: Tue, 08 Nov 2022 11:30:33 GMT
< x-cache: TCP_MISS from a23-55-45-84.deploy.akamaitechnologies.com (AkamaiGHost/10.10.1-44825277) (-)
< vary: Accept-Encoding
< vary: Accept-Encoding
< 
* Connection #0 to host api.music.apple.com left intact
% 

ついでに URL の部分を検索用のものに変えてみます。

「"https://api.music.apple.com/v1/catalog/jp/search?term=B'z&types=artists"」

で、実行。

% curl -v -H 'Authorization: Bearer eyJhbGc_o_JFUzIoN_IsImtpZBI6Iks3XEs1XUI1oFE_LBJoeXB_o_JKVoQ_fQ.eyJpc3M_o_JaoXlENXc3MjZUI_w_aWFoIjoxNDM3MXc5MDM1LBJleHB_ojEooXMyoXgxMDA9.QgQS5gv75mSJMw5Hw5rIoUFUx1-IYyXIsau_Lkv6oMS-GKeLk_XuIWW6aRZ-Ex3-7KUAzMJIR5yHznvw5XIkkB' "https://api.music.apple.com/v1/catalog/jp/search?term=B'z&types=artists"

するとレスポンスの最後、B'z にまつわる情報が返ってきているのが分かるかと思います。

*   Trying 23.56.16.9:443...
* Connected to api.music.apple.com (23.56.16.9) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: businessCategory=Private Organization; jurisdictionCountryName=US; jurisdictionStateOrProvinceName=California; serialNumber=C0806592; C=US; ST=California; L=Cupertino; O=Apple Inc.; OU=management:idms.group.1208920; CN=itunes.apple.com
*  start date: Apr 25 16:27:49 2022 GMT
*  expire date: May 25 16:27:48 2023 GMT
*  subjectAltName: host "api.music.apple.com" matched cert's "api.music.apple.com"
*  issuer: C=US; O=Apple Inc.; CN=Apple Public EV Server RSA CA 2 - G1
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fedf900b600)
> GET /v1/catalog/jp/search?term=B'z&types=artists HTTP/2
> Host: api.music.apple.com
> user-agent: curl/7.79.1
> accept: */*
> authorization: Bearer eyJhbGc_o_JFUzIoN_IsImtpZBI6Iks3XEs1XUI1oFE_LBJoeXB_o_JKVoQ_fQ.eyJpc3M_o_JaoXlENXc3MjZUI_w_aWFoIjoxNDM3MXc5MDM1LBJleHB_ojEooXMyoXgxMDA9.QgQS5gv75mSJMw5Hw5rIoUFUx1-IYyXIsau_Lkv6oMS-GKeLk_XuIWW6aRZ-Ex3-7KUAzMJIR5yHznvw5XIkkB
> 
< HTTP/2 200 
< server: 4.0.0
< content-type: application/json;charset=utf-8
< x-apple-jingle-correlation-key: JOSXR57OF2OG2ZRUJKOEOZVJRA
< x-apple-request-uuid: 4ba578f7-ee2e-9c6d-6634-4a9c4766a988
< b3: 4ba578f7ee2e9c6d66344a9c4766a988-0b03f71f5b294b1c
< x-b3-traceid: 4ba578f7ee2e9c6d66344a9c4766a988
< x-b3-spanid: 0b03f71f5b294b1c
< apple-seq: 0.0
< apple-tk: false
< apple-originating-system: MZStorePlatform
< x-apple-application-site: ST11
< x-apple-application-instance: 2534673
< x-responding-instance: MZStorePlatform:2534673:::
< apple-timing-app: 88 ms
< access-control-allow-origin: *
< strict-transport-security: max-age=31536000; includeSubDomains
< is-jetty: true
< x-daiquiri-instance: daiquiri:41896004:st53p00it-qujn15040101:7987:22RELEASE167:daiquiri-amp-store-l7shared-int-001-st
< x-daiquiri-instance: daiquiri:42282002:st53p00it-qujn13050102:7987:22RELEASE167:daiquiri-amp-store-l7shared-ext-001-st
< cache-control: public, no-transform, max-age=29
< date: Wed, 09 Nov 2022 00:22:40 GMT
< content-length: 8620
< x-cache: TCP_HIT from a23-55-45-84.deploy.akamaitechnologies.com (AkamaiGHost/10.10.1-44825277) (-)
< vary: Accept-Encoding
< vary: Accept-Encoding
< 
{"results":{"artists":{"href":"/v1/catalog/jp/search?limit=5&term=B%27z&types=artists","next":"/v1/catalog/jp/search?offset=5&term=B%27z&types=artists","data":[{"id":"74931253","type":"artists","href":"/v1/catalog/jp/artists/74931253","attributes":{"name":"B'z","genreNames":["ロック"],"artwork":{"width":2400,"height":2400,"url":"https://is5-ssl.mzstatic.com/image/thumb/Music122/v4/0c/88/58/0c885888-c769-81f8-8485-069cd9a362f1/pr_source.png/{w}x{h}bb.jpg","bgColor":"dcdfe6","textColor1":"000001","textColor2":"1b191e","textColor3":"2c2c2f","textColor4":"424046"},"url":"https://music.apple.com/jp/artist/bz/74931253"},"relationships":{"albums":{"href":"/v1/catalog/jp/artists/74931253/albums","next":"/v1/catalog/jp/artists/74931253/albums?offset=25","data":[{"id":"283000073","type":"albums","href":"/v1/catalog/jp/albums/283000073"},{"id":"292067907","type":"albums","href":"/v1/catalog/jp/albums/292067907"},{"id":"666625900","type":"albums","href":"/v1/catalog/jp/albums/666625900"},{"id":"75682683","type":"albums","href":"/v1/catalog/jp/albums/75682683"},{"id":"1561574089","type":"albums","href":"/v1/catalog/jp/albums/1561574089"},{"id":"74937562","type":"albums","href":"/v1/catalog/jp/albums/74937562"},{"id":"666634430","type":"albums","href":"/v1/catalog/jp/albums/666634430"},{"id":"75681798","type":"albums","href":"/v1/catalog/jp/albums/75681798"},{"id":"1605118558","type":"albums","href":"/v1/catalog/jp/albums/1605118558"},{"id":"75356318","type":"albums","href":"/v1/catalog/jp/albums/75356318"},{"id":"1466937136","type":"albums","href":"/v1/catalog/jp/albums/1466937136"},{"id":"74933581","type":"albums","href":"/v1/catalog/jp/albums/74933581"},{"id":"75682153","type":"albums","href":"/v1/catalog/jp/albums/75682153"},{"id":"347013256","type":"albums","href":"/v1/catalog/jp/albums/347013256"},{"id":"74935606","type":"albums","href":"/v1/catalog/jp/albums/74935606"},{"id":"75354662","type":"albums","href":"/v1/catalog/jp/albums/75354662"},{"id":"1325460835","type":"albums","href":"/v1/catalog/jp/albums/1325460835"},{"id":"454667912","type":"albums","href":"/v1/catalog/jp/albums/454667912"},{"id":"297710855","type":"albums","href":"/v1/catalog/jp/albums/297710855"},{"id":"1561701429","type":"albums","href":"/v1/catalog/jp/albums/1561701429"},{"id":"74944705","type":"albums","href":"/v1/catalog/jp/albums/74944705"},{"id":"1567851939","type":"albums","href":"/v1/catalog/jp/albums/1567851939"},{"id":"75361124","type":"albums","href":"/v1/catalog/jp/albums/75361124"},{"id":"1567852104","type":"albums","href":"/v1/catalog/jp/albums/1567852104"},{"id":"75357159","type":"albums","href":"/v1/catalog/jp/albums/75357159"}]}}},{"id":"1236215587","type":"artists","href":"/v1/catalog/jp/artists/1236215587","attributes":{"name":"BZ","genreNames":["ヒップホップ/ラップ"],"artwork":{"width":3000,"height":3000,"url":"https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/ae/b6/fb/aeb6fb97-56ba-e8fd-083f-f8c21970a74f/artwork.jpg/{w}x{h}ac.jpg","bgColor":"0f1050","textColor1":"d6bcf7","textColor2":"9dafdf","textColor3":"ae99d5","textColor4":"818fc2"},"url":"https://music.apple.com/jp/artist/bz/1236215587"},"relationships":{"albums":{"href":"/v1/catalog/jp/artists/1236215587/albums","data":[{"id":"1612269170","type":"albums","href":"/v1/catalog/jp/albums/1612269170"},{"id":"1552528987","type":"albums","href":"/v1/catalog/jp/albums/1552528987"},{"id":"1170604377","type":"albums","href":"/v1/catalog/jp/albums/1170604377"},{"id":"1344358078","type":"albums","href":"/v1/catalog/jp/albums/1344358078"},{"id":"1501353949","type":"albums","href":"/v1/catalog/jp/albums/1501353949"},{"id":"1551034513","type":"albums","href":"/v1/catalog/jp/albums/1551034513"},{"id":"1502686217","type":"albums","href":"/v1/catalog/jp/albums/1502686217"},{"id":"1502573665","type":"albums","href":"/v1/catalog/jp/albums/1502573665"},{"id":"1544732805","type":"albums","href":"/v1/catalog/jp/albums/1544732805"},{"id":"1536654657","type":"albums","href":"/v1/catalog/jp/albums/1536654657"},{"id":"1549103433","type":"albums","href":"/v1/catalog/jp/albums/1549103433"},{"id":"1375096721","type":"albums","href":"/v1/catalog/jp/albums/1375096721"},{"id":"1561406752","type":"albums","href":"/v1/catalog/jp/albums/1561406752"},{"id":"1597875079","type":"albums","href":"/v1/catalog/jp/albums/1597875079"},{"id":"1566648690","type":"albums","href":"/v1/catalog/jp/albums/1566648690"},{"id":"1503527043","type":"albums","href":"/v1/catalog/jp/albums/1503527043"},{"id":"1448546746","type":"albums","href":"/v1/catalog/jp/albums/1448546746"},{"id":"1644747159","type":"albums","href":"/v1/catalog/jp/albums/1644747159"},{"id":"1629986398","type":"albums","href":"/v1/catalog/jp/albums/1629986398"},{"id":"1619147046","type":"albums","href":"/v1/catalog/jp/albums/1619147046"},{"id":"1606159561","type":"albums","href":"/v1/catalog/jp/albums/1606159561"},{"id":"1582431314","type":"albums","href":"/v1/catalog/jp/albums/1582431314"}]}}},{"id":"1465740891","type":"artists","href":"/v1/catalog/jp/artists/1465740891","attributes":{"name":"BZ","genreNames":["エレクトロニック"],"artwork":{"width":500,"height":500,"url":"https://is3-ssl.mzstatic.com/image/thumb/Features125/v4/9e/da/50/9eda50fb-495d-62dd-473e-7e5ad83209f7/pr_source.png/{w}x{h}bb.jpg","bgColor":"1a1615","textColor1":"f6c069","textColor2":"d8a971","textColor3":"ca9e58","textColor4":"b28c5e"},"url":"https://music.apple.com/jp/artist/bz/1465740891"},"relationships":{"albums":{"href":"/v1/catalog/jp/artists/1465740891/albums","data":[{"id":"838262440","type":"albums","href":"/v1/catalog/jp/albums/838262440"},{"id":"997882538","type":"albums","href":"/v1/catalog/jp/albums/997882538"},{"id":"964660751","type":"albums","href":"/v1/catalog/jp/albums/964660751"},{"id":"1212786159","type":"albums","href":"/v1/catalog/jp/albums/1212786159"},{"id":"1579770371","type":"albums","href":"/v1/catalog/jp/albums/1579770371"}]}}},{"id":"1585689464","type":"artists","href":"/v1/catalog/jp/artists/1585689464","attributes":{"name":"BZ","genreNames":["エレクトロニック"],"artwork":{"width":4000,"height":4000,"url":"https://is5-ssl.mzstatic.com/image/thumb/Music122/v4/ac/09/ab/ac09ab8c-1707-c6aa-a45e-9074649456f0/5059722847474_cover.jpg/{w}x{h}ac.jpg","bgColor":"03242f","textColor1":"d0cecc","textColor2":"21b9d9","textColor3":"a7acac","textColor4":"1b9bb7"},"url":"https://music.apple.com/jp/artist/bz/1585689464"},"relationships":{"albums":{"href":"/v1/catalog/jp/artists/1585689464/albums","data":[{"id":"776208953","type":"albums","href":"/v1/catalog/jp/albums/776208953"},{"id":"1612158034","type":"albums","href":"/v1/catalog/jp/albums/1612158034"},{"id":"1571657950","type":"albums","href":"/v1/catalog/jp/albums/1571657950"},{"id":"1581841967","type":"albums","href":"/v1/catalog/jp/albums/1581841967"},{"id":"1577141561","type":"albums","href":"/v1/catalog/jp/albums/1577141561"},{"id":"1577141651","type":"albums","href":"/v1/catalog/jp/albums/1577141651"},{"id":"1583900522","type":"albums","href":"/v1/catalog/jp/albums/1583900522"},{"id":"1620727001","type":"albums","href":"/v1/catalog/jp/albums/1620727001"},{"id":"1584610904","type":"albums","href":"/v1/catalog/jp/albums/1584610904"}]}}},{"id":"303385174","type":"artists","href":"/v1/catalog/jp/artists/303385174","attributes":{"name":"BZ","genreNames":["ヒップホップ/ラップ"],"artwork":{"width":996,"height":996,"url":"https://is1-ssl.mzstatic.com/image/thumb/Music112/v4/81/ef/b0/81efb079-e993-f42a-cfe1-6ece22673a2f/pr_source.png/{w}x{h}bb.jpg","bgColor":"1f1c2d","textColor1":"c7cea4","textColor2":"d0ba8c","textColor3":"a6ab8c","textColor4":"ad9a79"},"url":"https://music.apple.com/jp/artist/bz/303385174"},"relationships":{"albums":{"href":"/v1/catalog/jp/artists/303385174/albums","data":[{"id":"1447921556","type":"albums","href":"/v1/catalog/jp/albums/1447921556"},{"id":"1637062769","type":"albums","href":"/v1/catalog/jp/albums/1637062769"},{"id":"1517197555","type":"albums","href":"/v1/catalog/jp/albums/1517197555"},{"id":"1614079632","type":"albums","href":"/v1/catalog/jp/albums/1614079632"},{"id":"1558826365","type":"albums","href":"/v1/catalog/jp/albums/1558826365"},{"id":"1609298956","type":"albums* Connection #0 to host api.music.apple.com left intact
","href":"/v1/catalog/jp/albums/1609298956"},{"id":"1584989196","type":"albums","href":"/v1/catalog/jp/albums/1584989196"},{"id":"1522129749","type":"albums","href":"/v1/catalog/jp/albums/1522129749"},{"id":"1648328595","type":"albums","href":"/v1/catalog/jp/albums/1648328595"},{"id":"1635988163","type":"albums","href":"/v1/catalog/jp/albums/1635988163"}]}}}]}},"meta":{"results":{"order":["artists"],"rawOrder":["artists"]}}}%                                                                                                                      % 

見づらいので形を整えたものが下記です。

{
    "results": {
        "artists": {
            "href": "/v1/catalog/jp/search?limit=5&term=B%27z&types=artists",
            "next": "/v1/catalog/jp/search?offset=5&term=B%27z&types=artists",
            "data": [
                {
                    "id": "74931253",
                    "type": "artists",
                    "href": "/v1/catalog/jp/artists/74931253",
                    "attributes": {
                        "name": "B'z",
                        "genreNames": [
                            "ロック"
                        ],
                        "artwork": {
                            "width": 2400,
                            "height": 2400,
                            "url": "https://is5-ssl.mzstatic.com/image/thumb/Music122/v4/0c/88/58/0c885888-c769-81f8-8485-069cd9a362f1/pr_source.png/{w}x{h}bb.jpg",
                            "bgColor": "dcdfe6",
                            "textColor1": "000001",
                            "textColor2": "1b191e",
                            "textColor3": "2c2c2f",
                            "textColor4": "424046"
                        },
                        "url": "https://music.apple.com/jp/artist/bz/74931253"
                    },
                    "relationships": {
                        "albums": {
                            "href": "/v1/catalog/jp/artists/74931253/albums",
                            "next": "/v1/catalog/jp/artists/74931253/albums?offset=25",
                            "data": [
                                {
                                    "id": "283000073",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/283000073"
                                },
                                {
                                    "id": "292067907",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/292067907"
                                },
                                {
                                    "id": "666625900",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/666625900"
                                },
                                {
                                    "id": "75682683",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75682683"
                                },
                                {
                                    "id": "1561574089",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1561574089"
                                },
                                {
                                    "id": "74937562",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/74937562"
                                },
                                {
                                    "id": "666634430",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/666634430"
                                },
                                {
                                    "id": "75681798",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75681798"
                                },
                                {
                                    "id": "1605118558",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1605118558"
                                },
                                {
                                    "id": "75356318",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75356318"
                                },
                                {
                                    "id": "1466937136",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1466937136"
                                },
                                {
                                    "id": "74933581",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/74933581"
                                },
                                {
                                    "id": "75682153",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75682153"
                                },
                                {
                                    "id": "347013256",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/347013256"
                                },
                                {
                                    "id": "74935606",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/74935606"
                                },
                                {
                                    "id": "75354662",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75354662"
                                },
                                {
                                    "id": "1325460835",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1325460835"
                                },
                                {
                                    "id": "454667912",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/454667912"
                                },
                                {
                                    "id": "297710855",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/297710855"
                                },
                                {
                                    "id": "1561701429",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1561701429"
                                },
                                {
                                    "id": "74944705",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/74944705"
                                },
                                {
                                    "id": "1567851939",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1567851939"
                                },
                                {
                                    "id": "75361124",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75361124"
                                },
                                {
                                    "id": "1567852104",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1567852104"
                                },
                                {
                                    "id": "75357159",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/75357159"
                                }
                            ]
                        }
                    }
                },
                {
                    "id": "1236215587",
                    "type": "artists",
                    "href": "/v1/catalog/jp/artists/1236215587",
                    "attributes": {
                        "name": "BZ",
                        "genreNames": [
                            "ヒップホップ/ラップ"
                        ],
                        "artwork": {
                            "width": 3000,
                            "height": 3000,
                            "url": "https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/ae/b6/fb/aeb6fb97-56ba-e8fd-083f-f8c21970a74f/artwork.jpg/{w}x{h}ac.jpg",
                            "bgColor": "0f1050",
                            "textColor1": "d6bcf7",
                            "textColor2": "9dafdf",
                            "textColor3": "ae99d5",
                            "textColor4": "818fc2"
                        },
                        "url": "https://music.apple.com/jp/artist/bz/1236215587"
                    },
                    "relationships": {
                        "albums": {
                            "href": "/v1/catalog/jp/artists/1236215587/albums",
                            "data": [
                                {
                                    "id": "1612269170",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1612269170"
                                },
                                {
                                    "id": "1552528987",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1552528987"
                                },
                                {
                                    "id": "1170604377",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1170604377"
                                },
                                {
                                    "id": "1344358078",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1344358078"
                                },
                                {
                                    "id": "1501353949",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1501353949"
                                },
                                {
                                    "id": "1551034513",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1551034513"
                                },
                                {
                                    "id": "1502686217",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1502686217"
                                },
                                {
                                    "id": "1502573665",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1502573665"
                                },
                                {
                                    "id": "1544732805",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1544732805"
                                },
                                {
                                    "id": "1536654657",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1536654657"
                                },
                                {
                                    "id": "1549103433",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1549103433"
                                },
                                {
                                    "id": "1375096721",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1375096721"
                                },
                                {
                                    "id": "1561406752",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1561406752"
                                },
                                {
                                    "id": "1597875079",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1597875079"
                                },
                                {
                                    "id": "1566648690",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1566648690"
                                },
                                {
                                    "id": "1503527043",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1503527043"
                                },
                                {
                                    "id": "1448546746",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1448546746"
                                },
                                {
                                    "id": "1644747159",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1644747159"
                                },
                                {
                                    "id": "1629986398",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1629986398"
                                },
                                {
                                    "id": "1619147046",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1619147046"
                                },
                                {
                                    "id": "1606159561",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1606159561"
                                },
                                {
                                    "id": "1582431314",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1582431314"
                                }
                            ]
                        }
                    }
                },
                {
                    "id": "1465740891",
                    "type": "artists",
                    "href": "/v1/catalog/jp/artists/1465740891",
                    "attributes": {
                        "name": "BZ",
                        "genreNames": [
                            "エレクトロニック"
                        ],
                        "artwork": {
                            "width": 500,
                            "height": 500,
                            "url": "https://is3-ssl.mzstatic.com/image/thumb/Features125/v4/9e/da/50/9eda50fb-495d-62dd-473e-7e5ad83209f7/pr_source.png/{w}x{h}bb.jpg",
                            "bgColor": "1a1615",
                            "textColor1": "f6c069",
                            "textColor2": "d8a971",
                            "textColor3": "ca9e58",
                            "textColor4": "b28c5e"
                        },
                        "url": "https://music.apple.com/jp/artist/bz/1465740891"
                    },
                    "relationships": {
                        "albums": {
                            "href": "/v1/catalog/jp/artists/1465740891/albums",
                            "data": [
                                {
                                    "id": "838262440",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/838262440"
                                },
                                {
                                    "id": "997882538",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/997882538"
                                },
                                {
                                    "id": "964660751",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/964660751"
                                },
                                {
                                    "id": "1212786159",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1212786159"
                                },
                                {
                                    "id": "1579770371",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1579770371"
                                }
                            ]
                        }
                    }
                },
                {
                    "id": "1585689464",
                    "type": "artists",
                    "href": "/v1/catalog/jp/artists/1585689464",
                    "attributes": {
                        "name": "BZ",
                        "genreNames": [
                            "エレクトロニック"
                        ],
                        "artwork": {
                            "width": 4000,
                            "height": 4000,
                            "url": "https://is5-ssl.mzstatic.com/image/thumb/Music122/v4/ac/09/ab/ac09ab8c-1707-c6aa-a45e-9074649456f0/5059722847474_cover.jpg/{w}x{h}ac.jpg",
                            "bgColor": "03242f",
                            "textColor1": "d0cecc",
                            "textColor2": "21b9d9",
                            "textColor3": "a7acac",
                            "textColor4": "1b9bb7"
                        },
                        "url": "https://music.apple.com/jp/artist/bz/1585689464"
                    },
                    "relationships": {
                        "albums": {
                            "href": "/v1/catalog/jp/artists/1585689464/albums",
                            "data": [
                                {
                                    "id": "776208953",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/776208953"
                                },
                                {
                                    "id": "1612158034",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1612158034"
                                },
                                {
                                    "id": "1571657950",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1571657950"
                                },
                                {
                                    "id": "1581841967",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1581841967"
                                },
                                {
                                    "id": "1577141561",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1577141561"
                                },
                                {
                                    "id": "1577141651",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1577141651"
                                },
                                {
                                    "id": "1583900522",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1583900522"
                                },
                                {
                                    "id": "1620727001",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1620727001"
                                },
                                {
                                    "id": "1584610904",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1584610904"
                                }
                            ]
                        }
                    }
                },
                {
                    "id": "303385174",
                    "type": "artists",
                    "href": "/v1/catalog/jp/artists/303385174",
                    "attributes": {
                        "name": "BZ",
                        "genreNames": [
                            "ヒップホップ/ラップ"
                        ],
                        "artwork": {
                            "width": 996,
                            "height": 996,
                            "url": "https://is1-ssl.mzstatic.com/image/thumb/Music112/v4/81/ef/b0/81efb079-e993-f42a-cfe1-6ece22673a2f/pr_source.png/{w}x{h}bb.jpg",
                            "bgColor": "1f1c2d",
                            "textColor1": "c7cea4",
                            "textColor2": "d0ba8c",
                            "textColor3": "a6ab8c",
                            "textColor4": "ad9a79"
                        },
                        "url": "https://music.apple.com/jp/artist/bz/303385174"
                    },
                    "relationships": {
                        "albums": {
                            "href": "/v1/catalog/jp/artists/303385174/albums",
                            "data": [
                                {
                                    "id": "1447921556",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1447921556"
                                },
                                {
                                    "id": "1637062769",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1637062769"
                                },
                                {
                                    "id": "1517197555",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1517197555"
                                },
                                {
                                    "id": "1614079632",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1614079632"
                                },
                                {
                                    "id": "1558826365",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1558826365"
                                },
                                {
                                    "id": "1609298956",
                                    "type": "albums* Connection #0 to host api.music.apple.com left intact",
                                    "href": "/v1/catalog/jp/albums/1609298956"
                                },
                                {
                                    "id": "1584989196",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1584989196"
                                },
                                {
                                    "id": "1522129749",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1522129749"
                                },
                                {
                                    "id": "1648328595",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1648328595"
                                },
                                {
                                    "id": "1635988163",
                                    "type": "albums",
                                    "href": "/v1/catalog/jp/albums/1635988163"
                                }
                            ]
                        }
                    }
                }
            ]
        }
    },
    "meta": {
        "results": {
            "order": [
                "artists"
            ],
            "rawOrder": [
                "artists"
            ]
        }
    }
}

とりあえず無事認証済みの開発者としてアクセスできました。

【レンタルサーバーより断然優位】Python 実行のおすすめ VPS 5 選

*本ページはプロモーションが含まれています

使える技術と使えない技術

レンタルサーバー(共用サーバー)は安いし、Python の勉強だったりサービスの公開にも使えるなと思っているそこのあなた。ちょっと待ってください。

実はレンタルサーバーの Python には純粋な Python とは違う様々なクセがあるのをご存知でしたか?

ものによって SSH 接続できない仮想環境が使えないデータベースが操作できない等、まともに実行できないことも多々あります。

なぜエラーが出るんだろう

私自身、元々使っていたさくらのレンタルサーバーでの Python 実行を散々試行錯誤した結果、さくらの VPS を借りることにしました。

その経験を踏まえても、Python を動かすにはレンタルサーバーではなく VPS をおすすめします。

こちらの記事ではその理由とおすすめの VPS をあわせて紹介しますので、ぜひ参考にしてみてください。

また、一般的に「レンタルサーバー」というと「共用サーバー」のことを指す事が多いので、こちらの記事でも「共用サーバー」の意味で「レンタルサーバー」を使用します。

レンタルサーバー x Python のリスク

結論から言うと、レンタルサーバーで Python プログラミングを行うのは一部を除いて難易度が無駄に高いです。

その理由はレンタルサーバーならではの権限の制限。Python 開発に必要な環境が作れない事がしばしばあります。

そしてそれを解決する術がない場合も多いのです。

1. 公式サイトと現実の違い

公式サイトで共用サーバーの仕様欄を見ると、大抵 Python3 と MySQL データベースの記載があるため一見問題なさそうです。

ただ、実際に使ってみるとさまざまな制限がかかっているのが共用サーバーです。

ざっくりいうと、物によって下記の様な事象があります。(他にもあるかも)

  • SSH 接続ができない → Python すら触れない
  • 仮想環境が使えない → 複数のアプリを作るのに向いていない
  • Python でデータベースが使えない → スクレイピング等に向いていない
Python が普通に使えるわけではありません

私が少し触って確認できたものだけでこんな感じなので、もっとプログラミングを進めていくと他にもいろいろ出てくる気はします。

詳しくは下記の記事も読んでみてください。

▶︎【7社比較】レンタルサーバーの大クセ Python は本当は使いづらい?

2. 環境構築からエラー頻発

プログラミングで物を作っていこうとすると様々なエラーが発生します。

これは普通のことで、都度調べて修正していくのがプログラミングです。

ただ、ここまで読んでいただいてわかる通り、レンタルサーバーでは環境構築の時点でエラーが発生しまくります。

環境構築というのは「Python を使える様にする」、「データベースを使える様にする」、などいわば準備段階です。レンタルサーバーではこの準備段階でつまづくため肝心のプログラミングに辿り着く前に心を折られます

3. レンタルサーバー x Python のエラーは情報が無い

そういった「レンタルサーバーならではのエラー」を調べても情報はほとんどなく、たとえ英語で調べても日本のレンタルサーバーに関連する情報は見つかりません。

そして散々時間をかけて調べた挙句「そもそも権限がないのでどうしようもない」という事が多々あります。

それも環境構築の段階でです。

レンタルサーバー特有のエラー

同じ労力を払うならVPSの方が有意義

ここまでレンタルサーバーの Python 環境構築がいかに難しいか説明してきましたが、その点 VPS は制限がほとんどないので逆にスムーズです。

VPSはハードルが高い様に思うかもしれませんが、Pythonを使う、データベースを使う、などに関してはレンタルサーバーよりもシンプルなケースが多いです。

また、Python プログラミングに関する既存の情報量は、レンタルサーバーと比べて VPS の方が圧倒的に多いです。

使えない技術 vs 使える技術

レンタルサーバーも VPS も、一筋縄では行かない事が多いです。

どうせ時間をかけるなら、レンタルサーバーでそもそも存在するかも分からない解決法を探るよりも、VPSで Linux 系サーバーの操作Python のプログラミング など、実践的な事を学んでいく方がコスパが良いと思いませんか?

使える技術と使えない技術

もし「将来的に業務でも使える様になれば」と考えているなら余計に VPS の方が良いです。業務の Python 実行環境にレンタルサーバーを使う会社は流石にないはずです。

そもそも VPS も月々 700 円〜900 円程度ですしね。

VPS はレンタルサーバーと比べて圧倒的に自由度が高く、「どの会社の VPS か」よりも「どの OS か」の方が重要だったりします。

詳しくはこちらの記事を参照いただければと思いますが、OS は既存情報の多い Ubuntu、Debian、CentOS がおすすめです。

後々エラーなどに出くわした際にも参考になる情報が多く便利です。

というわけでそろそろ「どの VPS がおすすめなのか」を説明します。

OS のインストールが簡単な VPS がおすすめ

実は、メジャーな VPS は大体 Ubuntu、Debian、CentOS に対応しています。ではその中で更に絞るには何を基準にしたらいいでしょうか。

ここは「OS インストールの簡単さ」で選びましょう。

実は VPS によっては特定の OS インストールをほぼ自動でやってくれるものがあります。

例えばさくらの VPS であればコントロールパネルで選択した OS を自動でインストールしてくれますし、GMO のクラウド VPS であれば契約時に選択した OS をインストールされた状態でサーバーが用意されます。

さらに ConoHa VPS に関しては Python のウェブ開発フレームワークである Django のセットアップまである程度自動化されています。

こうして選べば、インストールが簡単で問題解決もしやすい環境を整える事が出来ます。

各社の OS 自動インストールの対象は下記の通りです。

自動 OSConoHa VPSさくらの VPSお名前.com VPSGMO クラウド VPSKagoya Cloud VPS
Ubuntu
Debian
CentOS
その他Django テンプレ無料お試し

1. ConoHa VPS

ConoHa VPS
自動インストール対象 OSCentOS 7.1 〜 7.9
CentOS Stream 8
CentOS Stream 9
Ubuntu 18.04
Ubuntu 20.04
Debian 9.13
Debian 10.10
Debian 11.0
自動インストール方法サーバー追加時にテンプレートを選択することでサーバー作成と同時にOSのインストールやアプリケーションサーバーの構築が完了。

公式ページVPS を追加する
おすすめプラン1G(初期費用無料 + 月額 723 円〜)

解説

今回紹介する中で対応 OS の種類が最も豊富なのがこちらの ConoHa VPS。

「VPSをもっと速く、かんたんに」というキャッチコピーだけあって、OS だけでなく Django のテンプレートもあり、簡単にセットアップが可能です。「Django のインストールは自分でやりたい」という方はもちろんそれも可能です。

自動インストール対象の OS の種類も多いですし、下の記事の様に公式が親切に色々な情報を載せているのもポイントです。

3 ステップで簡単に始められるとの事で、公式サイトに「たったの25秒で〜サーバーが作れます。」とありますので試してみてください。笑

公式サイトConoHa VPS

2. さくらの VPS

さくらのVPS
自動インストール対象 OSUbuntu 18.04
Ubuntu 20.04
CentOS 7
CentOS Stream 8
自動インストール方法VPSコントロールパネルからワンクリックで再インストールが可能。

公式ページさくらの VPS 新規追加(コントロールパネル)
おすすめプラン1G(初期費用無料 + 月額 880 円〜)

解説

かなり気軽に使える VPS で、私自身もさくらの VPS を使っています。ポートの開閉をコントロールパネル上のクリックで行えるパケットフィルター機能が地味に楽です。

ユーザーへのサポートをかなり意識していて、公式サイトでも VPS のセットアップの手順を詳しく説明してくれているのもありがたいです。

ネコでもわかる!さくらのVPS講座 ~第二回「サーバーをさわってみよう!」

「Django VPS」で検索すると最も日本語記事が出てくるのは「さくらの VPS」です。

公式サイトさくらのVPS

3. お名前.com VPS

お名前.com VPS
自動インストール対象 OSUbuntu 18.04
Ubuntu 20.04
CentOS 7.5 ~ 7.9
CentOS Stream 8
Debian 9.13
Debian 10.10
自動インストール方法VPSコントロールパネルのサーバーセットアップで OS とバージョンを選択可能。

公式ページサーバーを初期セットアップする
おすすめプラン1G(初期費用無料 + 月額 873 円)

解説

オンラインでのお申込みから最短10分で利用開始できるというお名前.com の VPS。

KVM という仮想化方式を採用していて、ネットワークやディスクI/Oのパフォーマンスを良くする Virtio ドライバにも対応するなどハイパフォーマンスを追求している VPS

OS の初期インストールの方法は下記の公式ページに記載があります。

公式サイトお名前.com VPS

4. クラウドVPS by GMO

GMOクラウドのVPS 詳細はこちら
自動インストール対象 OSCentOS 7.9
CentOS 8.2
Ubuntu 20.04
Debian 10.0
自動インストール方法契約時に選択した OS をインストールした状態でサーバーが用意される。

公式ページ新規サーバー申し込み方法
おすすめプランV1(初期費用無料 + 月額 968 円〜)
お得な情報14 日間無料お試し

解説

コンテナ技術を採用していて、一般的な仮想マシンに比べて軽量で vCPU やメモリなどの負荷が小さく、リソースを効率的に利用できる VPS。どちらかというと法人ユーザーを想定しているようですが、14 日間の無料お試し期間があるのは他と違う点です 。

契約時の OS 選択について下記の公式ページで解説が載っています。

公式サイトGMOクラウドのVPS 詳細はこちら

5. KAGOYA Cloud VPS

カゴヤ・ジャパン
自動インストール対象 OSCentOS 7
CentOS 8
CentOS Stream 8
Ubuntu 18.04
Ubuntu 20.04
自動インストール方法専用コントロールパネルからテンプレートとアプリケーションを選択して環境構築可能。

公式ページインスタンス作成
おすすめプラン1コア/1GB(初期費用無料 + 月額 〜550 円)

解説

コントロールパネルから即座にスペック変更することができます

こちらもコントロールパネルからインスタンスを作成する際に任意の OS を指定することができます。

公式サイトカゴヤ・ジャパン

個人的には ConoHa VPS かさくらの VPS がおすすめ

OS インストールの手軽さを基準に Python のおすすめ VPS を 5 つ紹介しましたが、いかがだったでしょうか?

個人的なおすすめは ConoHa VPSさくらの VPS です。

ConoHa VPS は申し込み時の手軽ささくらの VPS は既に利用している人がかなりいる & 私自身も Django に利用していて全く不満がないからというのが理由です。

大量のデータを取り扱う大規模なアプリケーションを作成するのであれば GMO のクラウド VPSお名前.com の VPS(KVM)もいいかと思いますが、個人 Python プログラムを作っていく場合は前述の 2 つがおすすめです。

さくらレンタルサーバーでスクレイピング定期実行 & DB 保存

*本ページはプロモーションが含まれています

さくらのレンタルサーバを使ってスクレイピングをする方法をまとめます。

初めに言いますがページ遷移はカバーしていません。

eBay の商品情報を例としてページの要素を取得し、MySQL のデータベースに insert する一連の過程をまとめたいと思います。最後は CRON を使って定期実行させる設定も行います。

なので最低限 MySQL と CRON が使える「さくらのレンタルサーバ スタンダード」以上のプランを想定しています。

一応自分の忘備録としてまとめていますが、過程を追っていただければと思います。

  1. 実行環境の準備
  2. スクレイピングをしてみる
  3. データを保存する DB の作成
  4. Python からデータベースを操作する
  5. CRON で定期実行する

1. 実行環境の準備

さくらのレンタルサーバを契約する

まず始めるにあたってさくらのレンタルサーバを契約します。

冒頭でも書きましたが、データの保存と定期実行を行う前提なので MySQL と CRON が使える「さくらのレンタルサーバ スタンダード」以上のプランを使用します。

Python3 のインストール

サーバーへアクセスできる様になったら、Python3 をインストールして仮想環境を作成します。

さくらレンタルサーバのデフォルトの Python は Python2 なので Python3 を別途インストールする必要があります。下記の記事で手順を説明しています。

▶︎Python3 をインストールする方法

仮想環境の作成

Python3 のインストールが完了したら、任意の場所に仮想環境を作成します。

例として仮想環境「scraping_venv」を作成します。

% python3 -m venv scraping_venv
% 

仮想環境のパスに入り起動します。

% cd scraping_venv
% source bin/activate.csh
(scraping_venv) % 

3. スクレイピングをしてみる

では早速、requests モジュールを使ってページの情報を取得してみます。

requests のインストール

Web ページの取得に便利な requests をインストールするためコマンド「pip3 install requests」を実行します。

(scraping_venv) % pip3 install requests

インストールが完了したら Python3 を起動しますが、仮想環境を起動しているのでコマンド「python」で 起動できます。

(scraping_venv) % python
Python 3.9.0 (default, Jan  3 2021, 10:29:59) 
[GCC 4.2.1 20070831 patched [FreeBSD]] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>>

eBay ページの取得

requests をインポートし、requests.get() で URL「https://www.ebay.com/b/Video-Game-Consoles/139971/bn_320033」のソースコードを取得します。

>>> import requests
>>> r = requests.get('https://www.ebay.com/b/Video-Game-Consoles/139971/bn_320033')
>>> 

一旦変数 r に全部入ったので、r.text を実行するとソースコードが確認できます。

>>> r.text
'<!DOCTYPE html><!--[if IE 9]><html class="ie9" lang="ja"><![endif]--><!--[if gt IE 9]><!--><html lang="ja"><!--<![endif]--><head><style>\n    .font-marketsans body {\n        font-family: "Market Sans", Arial, sans-serif;\n    }\n</style><script>\n    (function() {\n        var useCustomFont = (\'fontDisplay\' in document.documentElement.style) ||\n                        (localStorage && localStorage.getItem(\'ebay-font\'));\n        if (useCustomFont) {\n            document.documentElement.classList.add(\'font-marketsans\');\n        }\n    })();\n</script><meta charset="utf-8"><link rel="'preconnect'" href="https://ir.ebaystatic.com" /><meta Property="og:description" Content="Shop eBay for great deals on ビデオゲームコンソール. You'll find new or used products in ビデオゲームコンソール on eBay. Free shipping on selected items." />

ソースコードを取得出来ることを確認できたので「exit()」を実行して一旦 Python のコンソールから出ます。

>>> exit() 
(scraping_venv) % 

Beautiful Soup で HTML 要素抽出

ページのソースを取得することはできたので、今度はそのソースコードから具体的な HTML の要素を抽出していきます。

HTML の取り扱いに便利な BeautifulSoup4 をインストールするためコマンド「pip3 install beautifulsoup4」を実行します。

(scraping_venv) % pip3 install beautifulsoup4

インストールが完了したら再度 Python3 を起動して BeautifulSoup と requestsをインポートします。

(scraping_venv) % python3
>>> from bs4 import BeautifulSoup
>>> import requests
>>> 

とりあえず eBay のページからサムネイル URL、商品名、商品ページ URL を取得したいと思います。

>>> r = requests.get('https://www.ebay.com/b/Video-Game-Consoles/139971/bn_320033')
>>> soup = BeautifulSoup(r.text,'html.parser')
>>> sitem = soup.find_all('li',class_='s-item') # クラス名が「s-item」の li 要素のリストを取得

Chrome のデベロッパーツールでページの構造を確認したところ、どうやらサムネイル URL、商品名、商品ページ URL は li 要素の中に含まれていて、その li 要素のクラス名が s-item だったので上記の様に取得しました。

取得した li 要素はリスト形式になっているので、for ループで各 li 要素からそれぞれの項目を抽出し、print していきます。

>>> for li in sitem: # 各 li 要素に対して処理を行う
...     img = li.find('img') # li 要素内の img 要素を取得
...     img_src = img.get('src') # img 要素内の src 属性を取得
...     name = li.find('h3') # li 要素内の h3 要素を取得
...     name_text = name.text # h3 要素内の文字列を取得
...     link = li.find('a') # li 要素内の a 要素を取得
...     link_href = link.get('href') # a 要素内の href 属性を取得
...     print(img_src)
...     print(name_text)
...     print(link_href)
... 

Enter を2度押下するとプログラムが実行されサムネイル、商品名、商品ページ URL が交互に表出されます。

... 
https://i.ebayimg.com/thumbs/images/g/Tl0AAOSwZpJgOul6/s-l300.jpg
ソニー PS5 ブルーレイエディションコンソール ( ディスク版 ) - クリスマス前に配達 !
https://www.ebay.com/p/19040936896?iid=154349758236
https://i.ebayimg.com/thumbs/images/g/AD4AAOSw3YphYRwA/s-l300.jpg
オリジナルNintendo EntertainmentシステムビデオゲームバンドルセットキットNESコンソールOG
https://www.ebay.com/p/101801921?iid=333818163486
https://i.ebayimg.com/thumbs/images/g/910AAOSwV5FhgtgV/s-l300.jpg
ソニー PS5 PlayStation 5 デジタル版コンソール-クリスマス配信前 !
https://www.ebay.com/p/25040975636?iid=154369068285

〜省略〜

https://ir.ebaystatic.com/cr/v/c1/s_1x2.gif
Microsoft Xbox One Day One Edition - 500 ギガバイトコンソールキネクトボックスコントローラテスト済み
https://www.ebay.com/itm/284613629401?hash=item42444b55d9:g:jBkAAOSwqldh5hbZ
https://ir.ebaystatic.com/cr/v/c1/s_1x2.gif
Nintendo Wii コンソール RVL-001 パワーリード 、 TVリード 、 センサーバー付き
https://www.ebay.com/itm/165287981385?hash=item267bee7149:g:I00AAOSwibph5VVv
https://ir.ebaystatic.com/cr/v/c1/s_1x2.gif
カシオゲームカンフーファイトCG - 310 ハンドヘルドゲーム 1990
https://www.ebay.com/itm/125105279976?hash=item1d20db13e8:g:J-IAAOSwn8dh5cND
>>> 

無事情報の抽出が出来ることを確認できたので、一旦「exit()」で Python のコマンドプロンプトから出ます。

>>> exit()
(scraping_venv) % 

同じ処理を Python ファイルで実行

一括で処理を実行できる様に、これまで実行したコマンドをまとめて下記のように一つのファイル(ebay_scraping.py)にまとめました。

# ebay_scraping.py
from bs4 import BeautifulSoup
import requests

r = requests.get('https://www.ebay.com/b/Video-Game-Consoles/139971/bn_320033')
soup = BeautifulSoup(r.text,'html.parser')
sitem = soup.find_all('li',class_='s-item') # クラス名が「s-item」の li 要素のリストを取得

for li in sitem: # 各 li 要素に対して処理を行う
    img = li.find('img') # li 要素内の img 要素を取得
    img_src = img.get('src') # img 要素内の src 属性を取得
    name = li.find('h3') # li 要素内の h3 要素を取得
    name_text = name.text # h3 要素内の文字列を取得
    link = li.find('a') # li 要素内の a 要素を取得
    link_href = link.get('href') # a 要素内の href 属性を取得
    print(img_src)
    print(name_text)
    print(link_href)

これを仮想環境「scraping_venv」直下にアップロードします。

そしてコマンド「python3 ebay_scraping.py」を実行します。

(scraping_venv) % python3 ebay_scraping.py
https://i.ebayimg.com/thumbs/images/g/Tl0AAOSwZpJgOul6/s-l300.jpg
ソニー PS5 ブルーレイエディションコンソール ( ディスク版 ) - クリスマス前に配達 !
https://www.ebay.com/p/19040936896?iid=154349758236
https://i.ebayimg.com/thumbs/images/g/GygAAOSwehBh5hlm/s-l300.jpg
ソニー PSP-3000 コンソール キングダム ハートゲームコンソール モンスターハンターゲームソフト付き
https://www.ebay.com/itm/313838198557?hash=item491236df1d:g:GygAAOSwehBh5hlm
https://i.ebayimg.com/thumbs/images/g/AD4AAOSw3YphYRwA/s-l300.jpg
オリジナルNintendo EntertainmentシステムビデオゲームバンドルセットキットNESコンソールOG
https://www.ebay.com/p/101801921?iid=333818163486

〜省略〜

https://ir.ebaystatic.com/cr/v/c1/s_1x2.gif
新品 ソニー PS4 Playstation 4 コンソール 1 TBスリム-新品送料無料
https://www.ebay.com/p/13031982632?iid=255337489506
https://ir.ebaystatic.com/cr/v/c1/s_1x2.gif
Nintendo GameCubeモデルNo. DOL -101 コンソールパーツと修理のみゲーム付き
https://www.ebay.com/itm/165288586955?hash=item267bf7aecb:g:TIgAAOSwZf9h5cbT
https://ir.ebaystatic.com/cr/v/c1/s_1x2.gif
Nintendo GameCube リージョンスイッチ付き LED mod カスタムコントローラ付き
https://www.ebay.com/itm/165288874148?hash=item267bfc10a4:g:u1cAAOSw3MJh5fWT
(scraping_venv) % 

無事サムネイル、商品名、商品ページ URL、が表出されました。ページに掲載される商品がタイミングによって違うので前回の実行時と若干内容が変わっています。

4. データベースの作成

ここまではただターミナル上に print してきましたが、これらの情報をデータベースに保存できる様にします。

さくらレンタルのコントロールパネルでデータベース作成

コントロールパネルのデータベースのセクションで「新規追加」をクリックします。

WordPress を使っている場合はそのデータベースが既にあると思いますが、何かを間違えて WordPress 用のテーブルに影響が出ると良くないので新規のデータベースを作ることをお勧めします。

無事新たなデータベースが作成されたので phpMyAdmin へログインします。

phpMyAdmin でテーブル作成

ログインした後、先ほど作成したデータベースを選択するとテーブル作成の画面に遷移すると思います。

テーブル名を入力して「Go」をクリックします。

カラム名、形式、長さを入力して「Save」をクリックします。

これでテーブル作成は完了です。下記のように反映されていると思います。

これでデータベースとその中にテーブルが出来上がりました。

5. Python からデータベースを操作する

では Python プログラムで抽出した情報をそのままデータベースのテーブルに insert 出来るようにしていきます。

MySQLdb モジュールで操作する

まずは Python で MySQL を操作するために必要な MySQLdb モジュールを使える様、ピp3で「mysqlclient」をインストールします。

(scraping_venv) % pip3 install mysqlclient

インストールしたら Python を起動し、MySQLdb をインポートしてデータベースに接続します。

(scraping_venv) % python3
>>> import MySQLdb
>>> conn = MySQLdb.connect(host='データベースサーバ', db='データベース名',user='ユーザー名',passwd='パスワード',charset='utf8mb4')
>>>

そして試しに先ほど作成したテーブル「ebay_products」に select クエリを叩いてみます。

>>> c = conn.cursor()
>>> c.execute('select * from ebay_products')
0
>>> 

まだデータを何も入れていないので 0 と返ってきています。動作は特に問題なさそうです。

Python ファイルに追記する

では先ほど作成した ebay_scraping.py を編集します。

MySQLdb モジュールでデータベースに接続する部分と合わせて、データを print する代わりにテーブルへ insert する様変更します。

# ebay_scraping.py
from bs4 import BeautifulSoup
import requests
import MySQLdb # 追記分

# 追記分↓
conn = MySQLdb.connect(host='データベースサーバー', db='データベース名',user='ユーザー名',passwd='パスワード',charset='utf8mb4')
c = conn.cursor()
# 追記分↑

r = requests.get('https://www.ebay.com/b/Video-Game-Consoles/139971/bn_320033')
soup = BeautifulSoup(r.text,'html.parser')
sitem = soup.find_all('li',class_='s-item')

for li in sitem:
    img = li.find('img')
    img_src = img.get('src')
    name = li.find('h3')
    name_text = name.text
    link = li.find('a')
    link_href = link.get('href')
    # print(img_src)
    # print(name_text)
    # print(link_href)
    # 追記分↓
    c.execute('insert into ebay_products values("'+img_src+'","'+name_text+'","'+link_href+'")')
    
conn.commit()
# 追記分↑

ではファイルを実行してみます。

(scraping_venv) % python3 ebay_scraping.py
(scraping_venv) % 

phpMyAdmin で対象のテーブルを開くとちゃんとデータが入っています。

これで eBay からデータを取得してデータベースへ保存するところまで出来ました。

6. CRON で定期実行する

作成したプログラムを定期的に実行する上で便利なのが CRON です。さくらのコントロールパネルから設定できるのでこの際やってみましょう。

コントロールパネル左下の「スクリプト設定」>「CRON設定」を開き「スケジュール追加」をクリックします。

設定画面が開くので実行コマンドと実行日時を設定します。毎日 21:00 に実行する設定にします。

「実行コマンド」欄は今回の場合「cd 実行ファイルのパス; Python3 の絶対パス 実行ファイル名」の形で下記の様に入力します。

cd www/notemite/scraping_venv; /home/ユーザー名/local/python/bin/python3 ebay_scraping.py

Python3 の絶対パスはコマンド「which python3」で確認できます。

% which python3
/home/ユーザー名/local/python/bin/python3

「保存する」をクリックして CRON 設定は完了です。

これで毎日 21:00 に ebay_scraping.py が実行され、取得したデータがデータベースのテーブルに insert されていきます。

複数処理を順に実行したい場合

余談ですが、設定できる CRON の数には限りがあるので、一つの処理につき一つの CRON を設定するとすぐ使い切ってしまいます。

なので例えば process_A.py、process_B.py、process_C.py という順番で実行したいプログラムがあった場合、まず CRON 設定の実行コマンドに下記を記述します。

cd www/notemite/scraping_venv; /bin/sh multiple_process.sh

これで CRON からは multiple_process.sh が実行されるので、個別のファイルと同じディレクトリに multiple_process.sh というファイルを作成し下記のように記述します。

#!/bin/sh
/home/ユーザー名/local/python/bin/python3 process_A.py &&
/home/ユーザー名/local/python/bin/python3 process_B.py &&
/home/ユーザー名/local/python/bin/python3 process_C.py

これによって CRON によって multiple_process.sh 呼び出され、まず process_A.py を実行、処理が成功したら process_B.py、さらにそれが成功したら process_C.py という具合に実行することができます。

レンタルサーバーの大クセPythonは要注意!どうしても使うならこれ

*本ページはプロモーションが含まれています

Python が普通に使えるわけではありません

Python を動かすためのレンタルサーバーを探しているそこのあなた。お待ちください。

実はレンタルサーバーでの Python 実行には下記のリスクがあるのをご存知でしたか?

  • SSH 接続できないかも
  • 仮想環境が使えないかも
  • データベースが操作できないかも
  • 最悪 Python の実行にすら辿りつかないかも
キーボード

不用意に怖がらせるつもりはないのですが、ネット上には公式サイトの仕様欄を鵜呑みにした記事が多く、実際自分が Python を使おうとした際に様々な問題にぶち当たりました。

その経験を踏まえ、当サイトでは実際に触って検証しましたので、ぜひサーバー選びの参考にしてみてください。

レンタルサーバーの Python は要注意

レンタルサーバーの公式サイトを見ると仕様欄に Python3 や MySQL が入っているので、何となく Python でプログラムを組みつつ MySQL のデータベースも使えてしまう様な気がしてきます。

が、実際使ってみるとそうもいきません。一つずつ見ていきましょう。

1. SSH 接続できないかも

まず SSH 接続が出来るかどうかの確認です。

SSH 接続とは
Windowsのコマンドプロンプトや Mac のターミナルなどを使ってサーバーを遠隔操作する方法

せっかくサーバーを借りても、SSH 接続が出来ないと Python の実行やパッケージのインストールなどが出来ません

ほとんどの共用サーバーは SSH 接続可能なので、ここはそこまで心配いらないと思いきや、スターサーバーでは SSH 接続出来ません。要注意です。

なぜ公式サイトで「Python」の記載があったのか分かりません。

XREAロリポップエックスサーバーコアサーバーConoha WINGバリューサーバースターサーバー
SSH 接続パスワードパスワード公開鍵公開鍵公開鍵パスワードNG

2. 仮想環境か使えないかも

次は Python の仮想環境が使えるかどうかの確認です。

仮想環境とは
例えば自分のパソコンに Python が入っていて、その中でスクレイピングのプログラムウェブサイト制作のプログラムの2つを作るとします。

それぞれのプログラムに必要なパッケージをインストールしていくと、どのパッケージがどちらのプログラムに使われているのか分からなくなったり、パッケージのアップデートなどでプログラム間の互換性が保てなくなることもあります。

この状況を整理するため、スクレイピング用の実行環境とウェブサイト制作用の実行環境を別々で作り、それぞれの中に必要なパッケージをインストールすることでお互いの干渉を防ぐのが仮想環境です。

これは公式サイトの仕様欄などを見ただけではわからないので、実際に仮想環境作成のコマンドを実行して確認してみました。

結果、そもそも SSH 接続も出来なかったスターサーバーに加え、バリューサーバーも仮想環境の作成ができませんでした。

逆に、それ以外のサーバーは問題なく仮想環境の作成ができました。

XREAロリポップエックスサーバーコアサーバーConoha WINGバリューサーバースターサーバー
SSH 接続パスワードパスワード公開鍵公開鍵公開鍵パスワードNG
仮想環境OKOKOKOKOKNG--

3. データベースが操作できないかも

レンタルサーバーで Python を使う際、最も気をつけなければならないのがPython でデータベースを使えるサーバーが少ないということです。

大抵のレンタルサーバーは WordPress には特化していて、数クリックで簡単にMySQL のデータベースが作成できることがほとんどですが、「Python でデータベースを操作する」となると話は別です。

mysqlclient モジュールのインストールが出来ない場合がある

共用サーバーで使用できるデータベースはほとんどの場合 MySQL ですが、Python で MySQL のデータベースを操作する場合は、mysqlclient モジュールをインストールする必要があります。

mysqlclent モジュール

実際にコマンドを実行して確認してみた結果、バリューサーバーやエックスサーバーなどでは mysqlclient のインストールで失敗しますし、ロリポップではサーバーに直接インストールはできるのに仮想環境で出来ないというクセもあります。

これも公式サイトの仕様欄などを見ただけではわからないので要注意です。

XREAロリポップエックスサーバーコアサーバーConoha WINGバリューサーバースターサーバー
SSH 接続パスワードパスワード公開鍵公開鍵公開鍵パスワードNG
仮想環境OKOKOKOKOKNG--
MySQLdbOKOK*不明*OK*不明NG--

また、上記の確認でデータベースを使えたとしても、レンタルサーバー特有の制限がかかっていて契約したレンタルサーバーからしかアクセスできない場合もありますので気をつけてください。

レンタルサーバーでのデータベース操作

つまり自分のパソコンからは操作できず、データベースを操作するスクリプトをレンタルサーバーに置いてそのスクリプトを実行するという様な回りくどい事をする羽目になります。

レンタルサーバー x Python ならほぼ XREA 一択

はい、というわけで SSH接続、仮想環境、MySQLdb 全て考慮すると、一番問題なく使えるのは XREA です。

XREA
公式サイトXREA
OSLinux (CentOS)
Python のバージョンPython2, Python3
データベース個数XREA Free:1
XREA Plus:5
CRONXREA Free:なし
XREA Plus:あり(個数不明)
ウェブ上の関連記事数多い
おすすめプランXREA Plus
(月額 210 円〜 + 初期費用 0 円)
無料お試し期間7 日間

ロリポップコアサーバーエックスサーバーに関しては SSH 接続と仮想環境の作成は問題ないですが、MySQLdb モジュールの使用に難ありです。

バリューサーバースターサーバーに関しては 仮想環境の作成も出来ないので Python の使用に関してはお勧めしません

その他の参考情報

ここまでで使えるサーバーがだいぶ絞られてしまいましたが、一応使えるデータベースの個数、CRON の個数、関連記事数も確認しましたので記載します。

1. 作成可能なデータベースの個数

Python でスクレイピングした情報など、データベースに保存したりデータベースから取り出したりする必要があります。その際、用途によってデータベースを分けたい場合もあると思いますので、作成可能なデータベースの個数も気にするといいと思います。

2. CRON の個数

CRON は指定した日時によって定期的にプログラムやスクリプトを実行できる機能です。スクレイピングやデータベースの更新など、CRON を使うと便利な場面が多いと思いますが、プランによって同時に設定できる CRON の個数が決まっているのでサーバーを選ぶ際には注目するといいと思います。

3. ウェブ上の関連記事数

サーバーの中で作業をしていく中で、必ず何かしらのエラーが起きて検索する必要があるのが常なので、検索した時にどの程度情報が出てくるかも大事なポイントです。検索結果の数も目安として掲載しますので参考にしてみてください。

ちなみに無料お試し期間があるサーバーも多いので、その間に Python3 を実際に試してみるのもありです。

各レンタルサーバーの検証内容

XREAロリポップエックスサーバーコアサーバーConoha WINGバリューサーバースターサーバー
Python バージョン2.x/3.x2.7/3.72.7/3.4/3.62.x/3.x2.7/3,62.7/3.62.7/3.4/3.6
SSH 接続パスワードパスワード公開鍵公開鍵公開鍵パスワードNG
仮想環境OKOKOKOKOKNG--
MySQLdbOKOK*不明*不明*不明NG--
データベース上限550無制限無制限無制限無制限30
CRON 上限個数不明10無制限不明不明9910
関連記事数多いかなり多いかなり多いかなり少ない多いかなり少ないかなり少ない
おすすめプランXREA PlusスタンダードスタンダードCORE-Xベーシックスタンダードスタンダード

1. XREA

XREA
公式サイトXREA
OSLinux (CentOS)
Python のバージョンPython2, Python3
データベース個数XREA Free:1
XREA Plus:5
CRONXREA Free:なし
XREA Plus:あり(個数不明)
ウェブ上の関連記事数多い
おすすめプランXREA Plus
(月額 210 円〜 + 初期費用 0 円)
無料お試し期間7 日間

SSH 接続

こちらはパスワードベースで SSH にログイン可能なので SSH 接続が簡単です。

Python 仮想環境

下記 4 行のコマンドだけで pip3 を使える状態の Python3 を起動できます。

$ bash
$ python3 -m venv python3-venv
$ source python3-venv/bin/activate
(python3-venv) $ python
>>> 

ただ、デフォルトのシェルが rbash でかなり制限があるので、SSH 接続したら初めにコマンド「bash」を実行する必要があります。上のスクリプトの1行目で「bash」と入力しているのがそれです。

MySQL モジュールの使用

上記に続けて下記を順に実行していけば仮想環境内で MySQLdb モジュールを使うこともできます。

>>> exit()
$ pip install mysqlclient
$ python
>>> import MySQLdb
>>> 

ウェブ上の関連記事数

「"XREA" "python3"」での検索結果は 5,020 件で、上の2つに比べると少ないですが、これでもよく調べれば普通の使い方には対応できるのではと思います。

おすすめプラン

XREA Free は無料ですが CRON が使えませんし、データベースも 1 つしか持てません。XREA Plus は CRON も使えてデータベースも 5 個まで作れるのでおすすめです。

利用開始するにはバリュードメインのアカウント(無料)作成も必要です。

公式サイトXREA

2. ロリポップ

ロリポップ!
公式サイトロリポップ!
OSLinux (CentOS)
Python のバージョンPython2.7, Python3.7
データベース個数ライトプラン:1
スタンダードプラン:50
CRON 個数ライトプラン:5
スタンダードプラン:10
ウェブ上の関連記事数かなり多い
おすすめプランスタンダード
(月額 440 円〜 + 初期費用 0 円)
無料お試し期間10 日間

SSH 接続

こちらも SSH へのログインはパスワードベースでなので分かりやすいです。

Python 仮想環境

SSH ログイン後はエックスサーバーと同じく下記 3 行のコマンドだけで pip3 を使える状態の Python3 を起動できました。本気で SSH ログインから 10 秒で Python3 を起動できます。

$ python3 -m venv python3-venv
$ source python3-venv/bin/activate
(python3-venv) $ python
>>> 

MySQL モジュールの使用

ただ、仮想環境内では MySQLdb モジュールがインストール出来ませんでした。仮想環境を作らずに Python3 を使うのであれば MySQLdb はすでに使えます。

$ python3
>>> import MySQLdb
>>> 

仮想環境外で追加パッケージをインストールする場合は「python3 -m pip install パッケージ名」でできる様です。

ウェブ上の関連記事数

「"ロリポップ" "python3"」での検索結果は 18,200 件と、こちらも多くの情報がすでにネット上に存在しています。

おすすめプラン

ライトだとMySQLデータベース1つしか作れないので、50個まで作れる「スタンダード」プランが良いと思います。

CRON もスタンダードプランであれば 10 個まで設定可能です。

こちらも無料お試し時にはクレジットカード情報などの入力は不要です。

公式サイトロリポップ!

3. エックスサーバー

エックスサーバー
公式サイトエックスサーバー
OSLinux
Python のバージョンPython2.7, Python3.4, Python3.6
データベース個数全プラン無制限
CRON 個数全プラン無制限
ウェブ上の関連記事数かなり多い
おすすめプランスタンダード
(月額 990 円 + 初期費用 3,300 円)
無料お試し期間10 日間

SSH 接続

SSH への接続は公開鍵認証の設定が必要で少し面倒ではあります。

Python 仮想環境

SSH ログインさえ出来れば下記のコマンドで pip3 を使える状態の Python3 を起動できます。

$ python3 -m venv python3-venv
$ source python3-venv/bin/activate
(python3-venv) $ python
>>> 

MySQLdb モジュールの使用

MySQLdb モジュールを使った MySQL の操作ですが、mysqlclient パッケージのインストールに失敗するという情報があります。

ウェブ上の関連記事数

「"エックスサーバー" "python3"」での検索結果は 12,500 件程度と、多くの情報がすでに存在しているので心強いです。

おすすめプラン

基本的な違いはディスクスペースの容量と無料独自ドメインの対象くらいなので「スタンダード」プランで充分だと思います。無料お試しに申し込んでもその時点ではクレジットカード情報などの入力が必要ないのも安心です。

CRON の個数は無制限です。データベースの個数も無制限です。すごいですね。

公式サイトエックスサーバー

4. コアサーバー

コアサーバー
公式サイトコアサーバー
OSLinux
Python のバージョンPython2, Python3
データベース個数全プラン無制限
CRON全プランあり(個数不明)
ウェブ上の関連記事数かなり少ない
おすすめプランCORE-X
(月額 399 円〜 + 初期費用 1,650 円)
無料お試し期間30 日間

SSH 接続

SSH への接続は公開鍵認証の設定が必要で少し面倒です。

Python 仮想環境

SSH ログイン後は他のサーバーと同じ様に「python3 -m venv 任意の仮想環境名」で仮想環境を作成できます。

$ python3 -m venv python3-venv
$ source python3-venv/bin/activate
(python3-venv) $ python
>>> 

ウェブ上の関連記事数

「"コアサーバー" "python3"」での検索結果は 500 件程度で、かなり少ない状態です。何か問題が起こったとき、まだ解決方法がネット上に載っていない場合も考えられます。

おすすめプラン

全プランで CRON あり、データベースの個数も無制限です。CORE-Xプランで十分足りると思います。

公式サイトコアサーバー

5. ConoHa WING

ConoHa WING
公式サイトConoHa WING
OSLinux (CentOS)
Python のバージョンPython2.7, Python3,6
データベース個数全プラン無制限
CRONあり(対象プラン及び個数不明)
ウェブ上の関連記事数多い
おすすめプランベーシック
(月額 740 円〜 + 初期費用 0 円)
無料お試し期間無し

SSH 接続

SSH への接続は公開鍵認証の設定が必要で少し面倒ではあります。

Python 仮想環境

SSH ログインさえ出来れば下記のコマンドで pip3 を使える状態の Python3 を起動できます。

$ python3 -m venv python3-venv
$ source python3-venv/bin/activate
(python3-venv) $ python
>>> 

ウェブ上の関連記事数

「"ConoHa WING" "python3"」での検索結果は 1,930 件で少し少ないかと思います。

おすすめプラン

データベースの個数は全プランで無制限です。 CRON は「ジョブスケジューラー」という名前で提供されていますが、個数はわかりませんでした。ベーシックプランがおすすめです。

公式サイトConoHa WING

6. バリューサーバー

バリューサーバー
公式サイトバリューサーバー
OSLinux
Python のバージョンPython2.7, Python3.6
データベース個数エコプラン:1
スタンダードプラン:無制限
CRON 個数エコプラン:10
スタンダードプラン:99
ウェブ上の関連記事数かなり少ない
おすすめプランスタンダード
(月額 367 円〜 + 初期費用 0 円)
無料お試し期間10 日間

SSH 接続

こちらもパスワードベースで SSH にログイン可能なので SSH 接続が簡単ですし、「python」でも「python3」でも Python3 が実行されるのも便利です。(Python2 の起動はコマンド python2 を実行)

Python 仮想環境

が、なぜか Python 仮想環境の作成時にエラーが発生します。

$ python3 -m venv python3-venv
Error: Command '['/virtual/アカウント名/python3-venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 2.

仮想環境外で mysqlclient をインストールしようとしてもエラーが発生するので、残念ながら Python の使用に関しては避けた方がいいと思います。

公式サイトバリューサーバー

7. スターサーバー

スターサーバー
公式サイトスターサーバー
OSLinux
Python のバージョンPython2.7, Python3.4, Python3.6
データベース個数ライト:1
スタンダード:30
CRON 個数ライト:5
スタンダード:10
ウェブ上の関連記事数かなり少ない
おすすめプランスタンダード
(月額 440 円〜 + 初期費用 0 円)
無料お試し期間14 日間

SSH 接続

何とスターサーバーは SSH 接続が出来ない仕様になっています。なので Python のコマンド操作なども出来ません。

公式サイトスターサーバー

おすすめは XREA

いかがでしたか?

学習も兼ねて Python を少しいじってみたいという場合は、既存の情報が多い上に SSH 接続、Python3 の実行、仮想環境の作成と全て問題なくできた XREA がおすすめです。

もし自分でも試したい場合は大体のレンタルサーバーが無料お試し期間を設けているので利用してみると良いかもしれません。お試し期間は基本的にクレジットカード情報など入力不要なので安心です。

更なるおすすめは VPS

最後に繰り返しになりますが、Python でプログラミングをしていくのであればレンタルサーバーよりも VPS がおすすめです。絶対に。

ご自身のためにも、下記の記事をチェックしてみてください。

▶︎レンタルサーバーで Python は要注意!VPS が楽得でおすすめ

【番外編】さくらレンタルで無理やり Python 3 と MySQL を使う

ちなみにさくらのレンタルサーバーはそもそも Python 2しか入っていないのでこの記事にも載せていないんですが(現在の推奨は Python 3 で Python 2 は非推奨)一応 Python 3 をインストールして仮想環境で MySQLdb をインストールすることも出来ました。

めんどくさすぎたので正直全くお勧めしないですが、気合いで頑張りたい方々のために一応貼っておきます。

【Ubuntu】Python の CaboCha をインストールして形態素解析を行う

Ubuntu 20.04 で CaboCha を使える様にした時の手順を記録しておきます。

  1. MeCab のインストール
  2. mecab-ipadic-neologd のインストール
  3. CRF++ のインストール
  4. CaboCha のインストール
  5. Pythonへのバインディング

まだインストールしていなければ build-essential をインストールします。

$ sudo apt install build-essential

1. MeCab のインストール

$ sudo apt install mecab
$ sudo apt install libmecab-dev
$ sudo apt install mecab-ipadic

この時点でコマンド「mecab」を実行して何か文章を入力すると MeCab が形態素解析をしてくれます。

$ mecab
今日はいい天気ですね。
今日	名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
いい	形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気	名詞,一般,*,*,*,*,天気,テンキ,テンキ
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
ね	助詞,終助詞,*,*,*,*,ね,ネ,ネ
。	記号,句点,*,*,*,*,。,。,。

2. mecab-ipadic-neologd のインストール

新語に対応した NEologd 辞書(mecab-ipadic-neologd)をインストールします。

$ cd /var/lib/mecab/dic
$ sudo git clone https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ sudo bin/install-mecab-ipadic-neologd

「/usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd」にインストールされたので、MeCab 実行時に「-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd」を渡してあげると mecab-ipadic-neologd を辞書として使うことができます。

$ mecab -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
霜降り明星が好きです。
霜降り明星	名詞,固有名詞,人名,一般,*,*,霜降り明星,シモフリミョウジョウ,シモフリミョウジョー
が	助詞,格助詞,一般,*,*,*,が,ガ,ガ
好き	名詞,形容動詞語幹,*,*,*,*,好き,スキ,スキ
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。	記号,句点,*,*,*,*,。,。,。
EOS

上では「霜降り明星」が一つの名詞として認識されていますが、デフォルトの辞書だと下記の様に「霜降り」と「明星」が別々の言葉として認識されています。

$ mecab
霜降り明星が好きです。
霜降り	名詞,一般,*,*,*,*,霜降り,シモフリ,シモフリ
明星	名詞,一般,*,*,*,*,明星,ミョウジョウ,ミョージョー
が	助詞,格助詞,一般,*,*,*,が,ガ,ガ
好き	名詞,形容動詞語幹,*,*,*,*,好き,スキ,スキ
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。	記号,句点,*,*,*,*,。,。,。
EOS

3. CRF++ のインストール

CRF++-0.58.tar.gz

$ cd
$ wget "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7QVR6VXJ5dWExSTQ" -O CRF++-0.58.tar.gz
$ tar zxvf CRF++-0.58.tar.gz
$ cd CRF++-0.58
$ ./configure
$ sudo ldconfig
$ rm CRF++-0.58.tar.gz

4. CaboCha のインストール

cabocha-0.68.tar.bz2 をダウンロードします。Google Drive に配置されているので少し複雑です。

$ FILE_ID=0B4y35FiV1wh7SDd1Q1dUQkZQaUU
$ FILE_NAME=cabocha-0.69.tar.bz2
$ curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=${FILE_ID}" > /dev/null
$ CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)"  
$ curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=${FILE_ID}" -o ${FILE_NAME}

cabocha-0.68.tar.bz2 を解凍、インストールしていきます。

$ bzip2 -dc cabocha-0.69.tar.bz2 | tar xvf -
$ cd cabocha-0.69
$ ./configure --with-mecab-config=`which mecab-config` --with-charset=UTF8
$ make
$ make check
$ sudo make install
$ sudo ldconfig

先程の MeCab を同じ様に、コマンド「cabocha」を実行して何か文章を入力すると CaboCha が係り受けを出してくれます。

$ cabocha
今日はいい天気ですね。
      今日は---D
          いい-D
    天気ですね。
EOS

5. Pythonへのバインディング

Python の仮想環境を立ち上げた状態で下記を実行します。

$ cd python
$ python setup.py install
$ pip install mecab-python3

下記の通り Python で CaboCha が使える様になりました。

>>> import CaboCha
>>> sentence = '霜降り明星(しもふりみょうじょう)は、2018年『M-1グランプリ』14代目王者。'
>>> c = CaboCha.Parser('-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd')
>>> print(c.parseToString(sentence))
        霜降り明星-----D      
              (しも-D |      
                  ふり-D      
      みょうじょう)は、-----D
                    2018年-D |
           『M-1グランプリ』-D
                  14代目王者。
EOS

【Python】CaboCha のツリーを XML から JSON に変換する

CaboCha のツリーを扱いたいのですがデフォルトでは JSON でのアウトプットがない様なので、xmltodict を利用して XML 形式から JSON 形式に変換します。

XML での表出

まず、XML の表出は下記の様になります。

import CaboCha

c = CaboCha.Parser()

tree = c.parse('今日は天気がとても良いですね。')
xmltree = tree.toString(CaboCha.FORMAT_XML)
print(xmltree)

XML アウトプット

<sentence>
 <chunk id="0" link="3" rel="D" score="-1.359140" head="0" func="1">
  <tok id="0" feature="名詞,副詞可能,*,*,*,*,今日,キョウ,キョー">今日</tok>
  <tok id="1" feature="助詞,係助詞,*,*,*,*,は,ハ,ワ">は</tok>
 </chunk>
 <chunk id="1" link="3" rel="D" score="-1.359140" head="2" func="3">
  <tok id="2" feature="名詞,一般,*,*,*,*,天気,テンキ,テンキ">天気</tok>
  <tok id="3" feature="助詞,格助詞,一般,*,*,*,が,ガ,ガ">が</tok>
 </chunk>
 <chunk id="2" link="3" rel="D" score="-1.359140" head="4" func="4">
  <tok id="4" feature="副詞,助詞類接続,*,*,*,*,とても,トテモ,トテモ">とても</tok>
 </chunk>
 <chunk id="3" link="-1" rel="D" score="0.000000" head="5" func="7">
  <tok id="5" feature="形容詞,自立,*,*,形容詞・アウオ段,基本形,良い,ヨイ,ヨイ">良い</tok>
  <tok id="6" feature="助動詞,*,*,*,特殊・デス,基本形,です,デス,デス">です</tok>
  <tok id="7" feature="助詞,終助詞,*,*,*,*,ね,ネ,ネ">ね</tok>
  <tok id="8" feature="記号,句点,*,*,*,*,。,。,。">。</tok>
 </chunk>
</sentence>

JSON での表出

xmltodict を使うので、インストールしていない場合はコマンド「pip install xmltodict」でインストールしてください。

import CaboCha
import xmltodict
import json

c = CaboCha.Parser()

tree = c.parse('今日は天気がとても良いですね。')
xmltree = tree.toString(CaboCha.FORMAT_XML)
jsonobj = xmltodict.parse(xmltree, attr_prefix='', cdata_key='surface', dict_constructor=dict)
print(json.dumps(jsonobj, indent=2, ensure_ascii=False))

JSON アウトプット

{
  "sentence": {
    "chunk": [
      {
        "id": "0",
        "link": "3",
        "rel": "D",
        "score": "-1.359140",
        "head": "0",
        "func": "1",
        "tok": [
          {
            "id": "0",
            "feature": "名詞,副詞可能,*,*,*,*,今日,キョウ,キョー",
            "surface": "今日"
          },
          {
            "id": "1",
            "feature": "助詞,係助詞,*,*,*,*,は,ハ,ワ",
            "surface": "は"
          }
        ]
      },
      {
        "id": "1",
        "link": "3",
        "rel": "D",
        "score": "-1.359140",
        "head": "2",
        "func": "3",
        "tok": [
          {
            "id": "2",
            "feature": "名詞,一般,*,*,*,*,天気,テンキ,テンキ",
            "surface": "天気"
          },
          {
            "id": "3",
            "feature": "助詞,格助詞,一般,*,*,*,が,ガ,ガ",
            "surface": "が"
          }
        ]
      },
      {
        "id": "2",
        "link": "3",
        "rel": "D",
        "score": "-1.359140",
        "head": "4",
        "func": "4",
        "tok": {
          "id": "4",
          "feature": "副詞,助詞類接続,*,*,*,*,とても,トテモ,トテモ",
          "surface": "とても"
        }
      },
      {
        "id": "3",
        "link": "-1",
        "rel": "D",
        "score": "0.000000",
        "head": "5",
        "func": "7",
        "tok": [
          {
            "id": "5",
            "feature": "形容詞,自立,*,*,形容詞・アウオ段,基本形,良い,ヨイ,ヨイ",
            "surface": "良い"
          },
          {
            "id": "6",
            "feature": "助動詞,*,*,*,特殊・デス,基本形,です,デス,デス",
            "surface": "です"
          },
          {
            "id": "7",
            "feature": "助詞,終助詞,*,*,*,*,ね,ネ,ネ",
            "surface": "ね"
          },
          {
            "id": "8",
            "feature": "記号,句点,*,*,*,*,。,。,。",
            "surface": "。"
          }
        ]
      }
    ]
  }
}

さらに改良

上記でも JSON 形式で返ってきますが、chunk や tok 要素の中身が 1 つしかない時にリスト形式になっていない、feature がカンマ区切りの文字列(リスト形式でない)になっているなど少し不便です。

下記の様に処理を追加するとフォーマットを揃えることができます。

import CaboCha
import xmltodict
import json

c = CaboCha.Parser()

tree = c.parse('今日は天気がとても良いですね。')
xmltree = tree.toString(CaboCha.FORMAT_XML)
jsonobj = xmltodict.parse(xmltree, attr_prefix='', cdata_key='surface', dict_constructor=dict)

# 追記分 ↓
if jsonobj['sentence']: # sentence が存在する際に処理を行う
    if type(jsonobj['sentence']['chunk']) is not list: # chunk を必ずリスト形式にする
        jsonobj['sentence']['chunk'] = [jsonobj['sentence']['chunk']]
    
    for chunk in jsonobj['sentence']['chunk']:
        if type(chunk['tok']) is not list: # tok を必ずリスト形式にする
            chunk['tok'] = [chunk['tok']]
        
        for tok in chunk['tok']:
            feature_list = tok['feature'].split(',') # feature をリスト形式に変換
            tok['feature'] = feature_list
# 追記分 ↑

print(json.dumps(jsonobj, indent=2, ensure_ascii=False))

JSON アウトプット ver 2

{
  "sentence": {
    "chunk": [
      {
        "id": "0",
        "link": "3",
        "rel": "D",
        "score": "-1.359140",
        "head": "0",
        "func": "1",
        "tok": [
          {
            "id": "0",
            "feature": [
              "名詞",
              "副詞可能",
              "*",
              "*",
              "*",
              "*",
              "今日",
              "キョウ",
              "キョー"
            ],
            "surface": "今日"
          },
          {
            "id": "1",
            "feature": [
              "助詞",
              "係助詞",
              "*",
              "*",
              "*",
              "*",
              "は",
              "ハ",
              "ワ"
            ],
            "surface": "は"
          }
        ]
      },
      {
        "id": "1",
        "link": "3",
        "rel": "D",
        "score": "-1.359140",
        "head": "2",
        "func": "3",
        "tok": [
          {
            "id": "2",
            "feature": [
              "名詞",
              "一般",
              "*",
              "*",
              "*",
              "*",
              "天気",
              "テンキ",
              "テンキ"
            ],
            "surface": "天気"
          },
          {
            "id": "3",
            "feature": [
              "助詞",
              "格助詞",
              "一般",
              "*",
              "*",
              "*",
              "が",
              "ガ",
              "ガ"
            ],
            "surface": "が"
          }
        ]
      },
      {
        "id": "2",
        "link": "3",
        "rel": "D",
        "score": "-1.359140",
        "head": "4",
        "func": "4",
        "tok": [
          {
            "id": "4",
            "feature": [
              "副詞",
              "助詞類接続",
              "*",
              "*",
              "*",
              "*",
              "とても",
              "トテモ",
              "トテモ"
            ],
            "surface": "とても"
          }
        ]
      },
      {
        "id": "3",
        "link": "-1",
        "rel": "D",
        "score": "0.000000",
        "head": "5",
        "func": "7",
        "tok": [
          {
            "id": "5",
            "feature": [
              "形容詞",
              "自立",
              "*",
              "*",
              "形容詞・アウオ段",
              "基本形",
              "良い",
              "ヨイ",
              "ヨイ"
            ],
            "surface": "良い"
          },
          {
            "id": "6",
            "feature": [
              "助動詞",
              "*",
              "*",
              "*",
              "特殊・デス",
              "基本形",
              "です",
              "デス",
              "デス"
            ],
            "surface": "です"
          },
          {
            "id": "7",
            "feature": [
              "助詞",
              "終助詞",
              "*",
              "*",
              "*",
              "*",
              "ね",
              "ネ",
              "ネ"
            ],
            "surface": "ね"
          },
          {
            "id": "8",
            "feature": [
              "記号",
              "句点",
              "*",
              "*",
              "*",
              "*",
              "。",
              "。",
              "。"
            ],
            "surface": "。"
          }
        ]
      }
    ]
  }
}

【Mac】Python の CaboCha をインストールして係り受け解析を行う

Mac 環境で Python の CaboCha を使って係り受け解析を行う方法を紹介します。

  1. MeCab、CRF++、CaboCha のインストール
    • MeCab のインストール
    • CRF++ と CaboCha のインストール
  2. CaboCha を使ってみる(Python 経由ではない)
  3. CaboCha の Python バインディング
    • 新たに仮想環境を作った場合
  4. Python で CaboCha を使う
    • 係り受け関係の出力
    • 形態素の出力
  5. NEologd 辞書で新語対応
    • NEologd 辞書のインストール
    • NEologd 辞書を使う

1. MeCab、CRF++、CaboCha のインストール

まず MeCab、CRF++ そして CaboCha をインストールするので、Python 仮想環境を起動した状態で下記を実行します。

MeCab のインストール

% brew install mecab
% brew install mecab-ipadic
% pip install mecab-python3

CRF++ と CaboCha のインストール

% brew install crf++
% brew install cabocha

2. CaboCha を使ってみる(Python 経由ではない)

上記をインストールするとターミナルで直接であれば CaboCha が使える様になります。

コマンド「cabocha」を実行してそのまま「今日は良い天気ですね。」と入力すると下記の様に出力されます。

% cabocha
今日は良い天気ですね。
      今日は---D
          良い-D
    天気ですね。
EOS

ただ、ここまでは Python を立ち上げずに直接 Shellscript で CaboCha を使っただけです。

3. CaboCha の Python バインディング

cabocha-0.69.tar.bz2 のリンクがあるのでここからダウンロードします。

Downloads フォルダに圧縮ファイルがありますね。

% cd Users/ユーザー名/Downloads
% ls
cabocha-0.69.tar.bz2

ファイルを解凍して、configure、make、make install を行います。

% tar xfv cabocha-0.69.tar.bz2
% cd cabocha-0.69
% ./configure --prefix=/usr/local/cabocha/0_69 --with-charset=UTF8 --with-posset=IPA
% make
% make install

Python の仮想環境を立ち上げた状態で「cabocha-0.69」直下の「python」フォルダに移動して「sudo python setup.py install」を実行します。

% cd python
% sudo python setup.py install

こうすると import CaboCha できる様になります。

ただ、Downloads フォルダから cabocha-0.69 ファイルを削除してもできる意味をまだいまいち理解できていません。仮想環境の site-packages に CaboCha.py は作られたんですけどそれで間に合ってるんですかね。後でログをよくみてみます。。。

追加の仮想環境を作った場合

すでに一度上記の行程を経て CaboCha を使っている場合、新たに追加の仮想環境を作る際にはいくつか行程を飛ばすことができます。

解凍した「cabocha-0.69」がある状態で「cabocha-0.69/python」ディレクトリに入り、新たに作った仮想環境を起動し、下記を実行すれば OK です。

% pip install mecab-python3
% cd cabocha-0.69/python
% sudo python setup.py install

4. Python で CaboCha を使う

とりあえず Python を立ち上げて「import CaboCha」もできますし下記の処理も実行できました。

>>> import CaboCha
>>> c = CaboCha.Parser()
>>> sentence = '今日は良い天気ですね。'
>>> print(c.parseToString(sentence))
      今日は---D
          良い-D
    天気ですね。
EOS

係り受け関係の出力

>>> tree =  c.parse(sentence)
>>> print(tree.toString(CaboCha.FORMAT_TREE))
      今日は---D
          良い-D
    天気ですね。
EOS

>>> print(tree.toString(CaboCha.FORMAT_LATTICE))
* 0 2D 0/1 -1.140323
今日	名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
* 1 2D 0/0 -1.140323
良い	形容詞,自立,*,*,形容詞・アウオ段,基本形,良い,ヨイ,ヨイ
* 2 -1D 0/2 0.000000
天気	名詞,一般,*,*,*,*,天気,テンキ,テンキ
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
ね	助詞,終助詞,*,*,*,*,ね,ネ,ネ
。	記号,句点,*,*,*,*,。,。,。
EOS

形態素の出力

形態素の文字列

>>> for i in range(tree.size()):
...     print(tree.token(i).surface)
... 
今日
は
良い
天気
です
ね
。
>>> 

形態素の情報

>>> for i in range(tree.size()):
...     print(tree.token(i).feature)
... 
名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
助詞,係助詞,*,*,*,*,は,ハ,ワ
形容詞,自立,*,*,形容詞・アウオ段,基本形,良い,ヨイ,ヨイ
名詞,一般,*,*,*,*,天気,テンキ,テンキ
助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
助詞,終助詞,*,*,*,*,ね,ネ,ネ
記号,句点,*,*,*,*,。,。,。
>>> 

5. NEologd 辞書で新語対応

デフォルトでは「IPA 辞書」という辞書が使用されますが、新語に対応するには「NEologd 辞書」が多く使用されている様です。

NEologd 辞書のインストール

通常の辞書「ipadic」が格納されているディレクトリに移動します。おそらく「/usr/local/lib/mecab/dic」もしくはそれに似た場所にあると思います。

% /usr/local/lib/mecab/dic
% ls
ipadic

git clone で「mecab-ipadic-neologd」を作成します。

% git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
% ls
ipadic			mecab-ipadic-neologd

「mecab-ipadic-neologd」フォルダに移動し、コマンド「./bin/install-mecab-ipadic-neologd -n -a」を実行します。

% cd mecab-ipadic-neologd
% ./bin/install-mecab-ipadic-neologd -n -a

途中「Do you want to install mecab-ipadic-NEologd? Type yes or no.」と聞かれるので「yes」と入力します。

これでインストール完了です。

NEologd 辞書を使う

CaboCha、MeCab を使用する際、デフォルトでは IPA 辞書が使用されるので、明示的に NEologd 辞書を指定する必要があります。

実行時に「-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd」を渡すのですが、下記コードの様に「CaboCha.Parser('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')」としてあげれば OK です。

import CaboCha

sentence = '霜降り明星(しもふりみょうじょう)は、2018年『M-1グランプリ』14代目王者。'

# IPA 辞書
c = CaboCha.Parser()
print('IPA 辞書:')
print(c.parseToString(sentence))

# NEologd 辞書
c = CaboCha.Parser('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
print('NEologd 辞書:')
print(c.parseToString(sentence))

上記を実行すると下記のアウトプットが返ってきます。

IPA 辞書:
      霜降り明星---D            
            (しも-D            
              ふりみ-D          
      ょうじょう)は、---------D
                  2018年---D   |
                      『M--D   |
               1グランプリ』-D |
                        14代目-D
                          王者。
EOS

NEologd 辞書:
        霜降り明星-----D      
              (しも-D |      
                  ふり-D      
      みょうじょう)は、-----D
                    2018年-D |
           『M-1グランプリ』-D
                  14代目王者。
EOS

「しもふりみょうじょう」や「M-1グランプリ」の部分が若干違いますね。

若干応用編として、YouTube のコメント欄を取得して形態素解析をしてみましたので下記に貼っておきます。

▶︎【Mac】Python の MeCab で YouTube コメントを 形態素解析にかける

Mac brew install mysqlclient でエラー pip install mysql で成功

環境

OS: macOS Big Sur バージョン 11.2.2
Python: Python 3.8.3

brew install mysqlclient でエラー

Python 仮想環境で「brew install mysqlclient」を実行したら下記のエラーが発生しました。結論から言うと「pip install mysqlclient」の間違いだったことに後で気づきました。

が、それに気づく前に「pip install mysql」を実行して無事解決したので書いておきます。

エラーログ

==> Searching for similarly named formulae...
These similarly named formulae were found:
mysql-client                                                                                  mysql-client@5.7
To install one of them, run (for example):
  brew install mysql-client
Error: No available formula or cask with the name "mysqlclient".
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.

とりあえず一番初めのエラー「Error: No available formula or cask with the name "mysqlclient".」が気になる。

調べてみると、「pip install mysql」を実行してその後に「pip install mysqlclient」を実行するという書き込みを発見。

ただ実際は「pip install mysql」だけで成功しました。

pip install mysql で成功

仮想環境内でコマンド「pip install mysql」を実行。

(venv) % pip install mysql
Collecting mysql
  Downloading https://files.pythonhosted.org/packages/bf/5f/b574ac9f70811df0540e403309f349a8b9fa1a25d3653824c32e52cc1f28/mysql-0.0.2.tar.gz
Collecting mysqlclient (from mysql)
  Downloading https://files.pythonhosted.org/packages/3c/df/59cd2fa5e48d0804d213bdcb1acb4d08c403b61c7ff7ed4dd4a6a2deb3f7/mysqlclient-2.0.3.tar.gz (88kB)
     |████████████████████████████████| 92kB 5.7MB/s 
Installing collected packages: mysqlclient, mysql
  Running setup.py install for mysqlclient ... done
  Running setup.py install for mysql ... done
Successfully installed mysql-0.0.2 mysqlclient-2.0.3
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(venv) %

「pip install mysql」で mysqlclient もカバーされている?

ログをみるとちらほら「mysqlclient」について書かれているのが見えると思います。

そして「Successfully installed mysql-0.0.2 mysqlclient-2.0.3」の一文も。これってストレートに「mysql と mysqlclient が無事インストールされました。」ってことですよね?

% pip install mysqlclient

なので python を立ち上げて「import MySQLdb」を実行してみたら特にエラーも出ず。

「pip install mysqlclient」を実行しても何も変わらず

ここまで来てやっと「brew install 〜」ではなく「pip install 〜」を実行すべきだったと気づいて「pip install mysqlclient」を実行してみましたが、すでに完了しているとのことで何も変わりませんでした。

(venv) % pip install mysqlclient
Requirement already satisfied: mysqlclient in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (2.0.3)
(venv) %

Python の YouTube Data API v3 でチャンネル・動画情報を取得する方法

YouTube Data API v3 では、YouTube 上の様々な情報を取得する事ができます。こちらの記事では API キーの作成からチャンネル、動画情報の取得までを解説します。

  1. API キーの作成
  2. ライブラリのインストール
  3. API リクエストを試してみる
  4. 取得できる情報

1. API キーの作成

「認証情報」のタブを開きます。

「+認証情報を作成」をクリックし「API キー」を選択。

黒く塗りつぶしてますが、ここに API キーが表示されます。

2. ライブラリのインストール

仮想環境内で Google APIs Client Library for Python をインストールします。

コマンド「pip install --upgrade google-api-python-client」を実行します。

(sample_venv) % pip install --upgrade google-api-python-client
Collecting google-api-python-client
  Downloading https://files.pythonhosted.org/packages/b7/56/bc7314cd180d1420e4ef11202dc9548ec22237a0a6de1aaf37b460ee7753/google_api_python_client-2.0.2-py2.py3-none-any.whl (6.5MB)
     |████████████████████████████████| 6.5MB 9.0MB/s 
Collecting google-auth<2dev,>=1.16.0 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/b5/ef/13d3b65c41ddde1a57e89de6adfc610093d109ebd472545a33e76dcdd8bf/google_auth-1.28.0-py2.py3-none-any.whl (136kB)
     |████████████████████████████████| 143kB 10.8MB/s 
Collecting google-api-core<2dev,>=1.21.0 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/66/21/891884b4fe2eda194e5cdc9ea617b63ab41e0aca595c865492380e2c10b3/google_api_core-1.26.2-py2.py3-none-any.whl (93kB)
     |████████████████████████████████| 102kB 11.4MB/s 
Collecting httplib2<1dev,>=0.15.0 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/15/7e/51e5bd333c0afa1c7bdbf98eb3b0ccf5167e2b1ecc8b4d13e9cc29291f81/httplib2-0.19.0-py3-none-any.whl (95kB)
     |████████████████████████████████| 102kB 11.4MB/s 
Collecting uritemplate<4dev,>=3.0.0 (from google-api-python-client)
  Using cached https://files.pythonhosted.org/packages/bf/0c/60d82c077998feb631608dca3cc1fe19ac074e772bf0c24cf409b977b815/uritemplate-3.0.1-py2.py3-none-any.whl
Collecting google-auth-httplib2>=0.0.3 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/ba/db/721e2f3f32339080153995d16e46edc3a7657251f167ddcb9327e632783b/google_auth_httplib2-0.1.0-py2.py3-none-any.whl
Requirement already satisfied, skipping upgrade: six<2dev,>=1.13.0 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-api-python-client) (1.15.0)
Collecting cachetools<5.0,>=2.0.0 (from google-auth<2dev,>=1.16.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/bb/72/8df2e0dc991f1a1d2c6869404e7622e8ee50d80bff357dbb57c3df70305b/cachetools-4.2.1-py3-none-any.whl
Collecting pyasn1-modules>=0.2.1 (from google-auth<2dev,>=1.16.0->google-api-python-client)
  Using cached https://files.pythonhosted.org/packages/95/de/214830a981892a3e286c3794f41ae67a4495df1108c3da8a9f62159b9a9d/pyasn1_modules-0.2.8-py2.py3-none-any.whl
Collecting rsa<5,>=3.1.4; python_version >= "3.6" (from google-auth<2dev,>=1.16.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/e9/93/0c0f002031f18b53af7a6166103c02b9c0667be528944137cc954ec921b3/rsa-4.7.2-py3-none-any.whl
Requirement already satisfied, skipping upgrade: setuptools>=40.3.0 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-auth<2dev,>=1.16.0->google-api-python-client) (41.2.0)
Collecting packaging>=14.3 (from google-api-core<2dev,>=1.21.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/3e/89/7ea760b4daa42653ece2380531c90f64788d979110a2ab51049d92f408af/packaging-20.9-py2.py3-none-any.whl (40kB)
     |████████████████████████████████| 40kB 8.7MB/s 
Requirement already satisfied, skipping upgrade: requests<3.0.0dev,>=2.18.0 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client) (2.25.1)
Collecting googleapis-common-protos<2.0dev,>=1.6.0 (from google-api-core<2dev,>=1.21.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/55/08/796a6bc0b550e2b7116041c953d3d5100016abea106131d71e5651826e7b/googleapis_common_protos-1.53.0-py2.py3-none-any.whl (198kB)
     |████████████████████████████████| 204kB 11.0MB/s 
Collecting protobuf>=3.12.0 (from google-api-core<2dev,>=1.21.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/62/be/f610958bf64f2a64b6b0b3403d17564af53bbfad5dad69f69b164cca038d/protobuf-3.15.6-cp38-cp38-macosx_10_9_x86_64.whl (1.0MB)
     |████████████████████████████████| 1.0MB 10.8MB/s 
Requirement already satisfied, skipping upgrade: pytz in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client) (2021.1)
Requirement already satisfied, skipping upgrade: pyparsing<3,>=2.4.2 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from httplib2<1dev,>=0.15.0->google-api-python-client) (2.4.7)
Collecting pyasn1<0.5.0,>=0.4.6 (from pyasn1-modules>=0.2.1->google-auth<2dev,>=1.16.0->google-api-python-client)
  Using cached https://files.pythonhosted.org/packages/62/1e/a94a8d635fa3ce4cfc7f506003548d0a2447ae76fd5ca53932970fe3053f/pyasn1-0.4.8-py2.py3-none-any.whl
Requirement already satisfied, skipping upgrade: certifi>=2017.4.17 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (2020.12.5)
Requirement already satisfied, skipping upgrade: chardet<5,>=3.0.2 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (4.0.0)
Requirement already satisfied, skipping upgrade: urllib3<1.27,>=1.21.1 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (1.26.4)
Requirement already satisfied, skipping upgrade: idna<3,>=2.5 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (2.10)
Installing collected packages: cachetools, pyasn1, pyasn1-modules, rsa, google-auth, packaging, protobuf, googleapis-common-protos, google-api-core, httplib2, uritemplate, google-auth-httplib2, google-api-python-client
Successfully installed cachetools-4.2.1 google-api-core-1.26.2 google-api-python-client-2.0.2 google-auth-1.28.0 google-auth-httplib2-0.1.0 googleapis-common-protos-1.53.0 httplib2-0.19.0 packaging-20.9 protobuf-3.15.6 pyasn1-0.4.8 pyasn1-modules-0.2.8 rsa-4.7.2 uritemplate-3.0.1
(sample_venv) %

3. API リクエストを試してみる

まずはブラウザの URL バーから

まずは Python 関係なく、単純にブラウザの URL バーに下記の URL を入れてみます。(APIキーはご自分のを入れてください)

https://youtube.googleapis.com/youtube/v3/channels?part=snippet%2CcontentDetails%2Cstatistics&id=UC_x5XG1OV2P6uZZ5FSM9Ttw&key=APIキー

すると下記の JSON テキストが表示されました。ID「UC_x5XG1OV2P6uZZ5FSM9Ttw」の Google Developers チャンネルの情報が取れました。

Python での実行

同じことを Python でやろうとすると下記の様なコードになるそうです。(Google のサイト参照

import os

import googleapiclient.discovery

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = "API キー"

    youtube = googleapiclient.discovery.build(api_service_name, api_version, developerKey = DEVELOPER_KEY)

    request = youtube.channels().list( # channels().list
        part="snippet,contentDetails,statistics", # 取得したい情報の指定
        id="UC_x5XG1OV2P6uZZ5FSM9Ttw" # チャンネル ID を指定(複数も可)
    )
    response = request.execute()

    print(response)

if __name__ == "__main__":
    main()

「part」に渡しているのが取得するデータの種類です。この記事の最後に取得できる part のリストを載せておきます。

動画情報の場合は下記の通り。個人的に好きで見てた FF 7 リメイクのプレイ動画です。 動画ID「fdsaZ8EMR2U」で指定しています。

import os

import googleapiclient.discovery

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = "API キー"

    youtube = googleapiclient.discovery.build(
        api_service_name, api_version, developerKey = DEVELOPER_KEY)

    request = youtube.videos().list( # videos().list
        part="contentDetails", # 取得したい情報の指定
        id="fdsaZ8EMR2U" # 動画 ID を指定(複数も可)
    )
    response = request.execute()

    print(response)

if __name__ == "__main__":
    main()

動画情報の part の内下記は投稿主のみアクセスできるそうです。

  • fileDetails
  • processingDetails
  • suggestions

そして急上昇ランキングを取る場合はこう。動画 ID の指定は消して「chart="mostPopular"」、「regionCode="JP"」、「maxResults=50」 を追記します。

JP(日本)の mostPopular(急上昇ランキング)から 50 件のデータを取るという意味です。

import os

import googleapiclient.discovery

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = "API キー"

    youtube = googleapiclient.discovery.build(
        api_service_name, api_version, developerKey = DEVELOPER_KEY)

    request = youtube.videos().list(
        part="snippet,contentDetails,statistics", # 取得したい情報の指定
        chart="mostPopular", # chart に「mostPopular」を指定
        maxResults=50, # 最大件数
        regionCode="JP" # 地域コード
    )
    response = request.execute()

    print(response)

if __name__ == "__main__":
    main()

実行すると下記の様な内容の dict データが取れるはずです。(実際は整形されていない状態)

{
  "kind": "youtube#videoListResponse",
  "etag": "jUM1iWDvm5ncH7VdFCrks9TZYQY",
  "items": [
    {
      "kind": "youtube#video",
      "etag": "jtNs4gdyS4wCzxvZKpEA0GbXJ0M",
      "id": "GOBeIaj7Ml0",
      "snippet": {
        "publishedAt": "2021-03-27T11:00:43Z",
        "channelId": "UCpOjLndjOqMoffA-fr8cbKA",
        "title": "【コムドット】生意気な後輩YouTuberと学校貸し切って本気でドロケイした結果【アバ溜りドット】",
        "description": "まだまだ道は開けない!!\n\nアバンティーズ\nhttps://www.youtube.com/user/avntisdouga\n\nコムドット \nhttps://www.youtube.com/channel/UCRxPrFmRHsXGWfAyE6oqrPQ\n\nフォーエイト とのドロケイ動画はこちらです!\nhttps://youtu.be/cbrQUkl6iD8\n\n動画がいいなと思っていただけたら高評価押してください!再生数よりもこちらを参考にして動画を作りたい!!そして少しでも面白いなと思っていただけたらぜひ【チャンネル登録】お願いします!\n\n水溜りボンドLINE公式アカウント!\nhttps://lin.ee/cVkWzGW\n最新情報不定期配信中!僕らからのメッセージも届きますよ!\nぜひ友だち登録してください!\n\nしゃべる!水溜りボンドLINEスタンプ\nhttps://00m.in/AcJcI\n水溜りボンドLINEスタンプ\nhttps://00m.in/2mzGU\n水溜りボンドのグッズはこちら!\nhttps://muuu.com/users/c7bf52c2b9fb5c5a\nおすすめでございます!!\n\n6年間1度も休まず毎日投稿しておりました!これからも少しでもみなさんが楽しんでいただければ幸いです。\n\n\n\n☆水溜りボンドを初めて知った方に是非見ていただきたい動画はこちら!☆\nhttps://www.youtube.com/watch?v=BvRvt6Nxny8\n\n●水溜りボンドの日常!僕らのサブチャンネルです。毎日比較的ゆったりやってます〜\nhttps://www.youtube.com/channel/UCaTFX7ckdowpnwHWcJGH2KQ\n\n\n●水溜りボンドのオールナイトニッポン0の詳細はこちらから\nぜひフォローお願いいたします!!\nhttps://twitter.com/mizuann0\n●限定動画や専用の絵文字など。チャンネルメンバーシップはこちらから!\nhttps://www.youtube.com/channel/UCpOjLndjOqMoffA-fr8cbKA/join\n\n◆Twitter\nカンタのアカウント\nhttps://twitter.com/kantamizutamari\nトミーのアカウント\nhttps://twitter.com/miztamari_nikki\n\n■インスタグラム\nカンタのアカウント\nhttps://bit.ly/2UckzeP\nトミーのアカウント\nhttps://www.instagram.com/tommymizutamaribond/\nーーーーーー\nよく使用している友人のBGM作曲者さん↓\nhttps://twitter.com/gt_k_2014?lang=ja\n素材提供 Music-Note.jp(ミュージックノート)\n他の楽曲提供:Production Music by http://www.epidemicsound.com\n素材提供 PIXTA\n\n#水溜りボンド\n#ドロケイ\n#コムドット",
        "thumbnails": {
          "default": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/default.jpg",
            "width": 120,
            "height": 90
          },
          "medium": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/mqdefault.jpg",
            "width": 320,
            "height": 180
          },
          "high": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/hqdefault.jpg",
            "width": 480,
            "height": 360
          },
          "standard": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/sddefault.jpg",
            "width": 640,
            "height": 480
          },
          "maxres": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/maxresdefault.jpg",
            "width": 1280,
            "height": 720
          }
        },
        "channelTitle": "水溜りボンド",
        "tags": [
          "水溜りボンド",
          "都市伝説",
          "検証",
          "実験",
          "科学",
          "お笑い",
          "面白",
          "面白い",
          "企画",
          "楽しい",
          "ワクワク",
          "カンタ",
          "トミー"
        ],
        "categoryId": "24",
        "liveBroadcastContent": "none",
        "defaultLanguage": "ja",
        "localized": {
          "title": "【コムドット】生意気な後輩YouTuberと学校貸し切って本気でドロケイした結果【アバ溜りドット】",
          "description": "まだまだ道は開けない!!\n\nアバンティーズ\nhttps://www.youtube.com/user/avntisdouga\n\nコムドット \nhttps://www.youtube.com/channel/UCRxPrFmRHsXGWfAyE6oqrPQ\n\nフォーエイト とのドロケイ動画はこちらです!\nhttps://youtu.be/cbrQUkl6iD8\n\n動画がいいなと思っていただけたら高評価押してください!再生数よりもこちらを参考にして動画を作りたい!!そして少しでも面白いなと思っていただけたらぜひ【チャンネル登録】お願いします!\n\n水溜りボンドLINE公式アカウント!\nhttps://lin.ee/cVkWzGW\n最新情報不定期配信中!僕らからのメッセージも届きますよ!\nぜひ友だち登録してください!\n\nしゃべる!水溜りボンドLINEスタンプ\nhttps://00m.in/AcJcI\n水溜りボンドLINEスタンプ\nhttps://00m.in/2mzGU\n水溜りボンドのグッズはこちら!\nhttps://muuu.com/users/c7bf52c2b9fb5c5a\nおすすめでございます!!\n\n6年間1度も休まず毎日投稿しておりました!これからも少しでもみなさんが楽しんでいただければ幸いです。\n\n\n\n☆水溜りボンドを初めて知った方に是非見ていただきたい動画はこちら!☆\nhttps://www.youtube.com/watch?v=BvRvt6Nxny8\n\n●水溜りボンドの日常!僕らのサブチャンネルです。毎日比較的ゆったりやってます〜\nhttps://www.youtube.com/channel/UCaTFX7ckdowpnwHWcJGH2KQ\n\n\n●水溜りボンドのオールナイトニッポン0の詳細はこちらから\nぜひフォローお願いいたします!!\nhttps://twitter.com/mizuann0\n●限定動画や専用の絵文字など。チャンネルメンバーシップはこちらから!\nhttps://www.youtube.com/channel/UCpOjLndjOqMoffA-fr8cbKA/join\n\n◆Twitter\nカンタのアカウント\nhttps://twitter.com/kantamizutamari\nトミーのアカウント\nhttps://twitter.com/miztamari_nikki\n\n■インスタグラム\nカンタのアカウント\nhttps://bit.ly/2UckzeP\nトミーのアカウント\nhttps://www.instagram.com/tommymizutamaribond/\nーーーーーー\nよく使用している友人のBGM作曲者さん↓\nhttps://twitter.com/gt_k_2014?lang=ja\n素材提供 Music-Note.jp(ミュージックノート)\n他の楽曲提供:Production Music by http://www.epidemicsound.com\n素材提供 PIXTA\n\n#水溜りボンド\n#ドロケイ\n#コムドット"
        },
        "defaultAudioLanguage": "ja"
      },
      "contentDetails": {
        "duration": "PT23M58S",
        "dimension": "2d",
        "definition": "hd",
        "caption": "false",
        "licensedContent": true,
        "contentRating": {},
        "projection": "rectangular"
      },
      "statistics": {
        "viewCount": "337770",
        "likeCount": "17557",
        "dislikeCount": "544",
        "favoriteCount": "0",
        "commentCount": "1650"
      }
    },
 

4. 取得できる情報(part)

確認できた範囲で、どの part にどんな項目が含まれているのか書き出しておきます。

取得できるチャンネル情報

チャンネルの part ではチャンネル名(title)、チャンネル登録者数(subscriberCount)、投稿動画数(videoCount)など、チャンネル単位の情報が取得できます。

part 名称配下の項目
auditDetails投稿主のみアクセス可
brandingSettingschannel, image
contentDetailsrelatedPlaylists
contentOwnerDetails
idチャンネル ID
localizations
snippettitle, description, customUrl, publishedAt, thumbnails, localized, country
statisticsviewCount, subscriberCount, hiddenSubscriberCount, videoCount
statusprivacyStatus, isLinked, longUploadsStatus, madeForKids
topicDetailstopicIds, topicCategories

取得できる動画情報

動画の part では動画タイトル(title)、動画再生回数(viewCount)、いいね数(likeCount)など、 動画単位の情報が取得できます。

part 名称配下の項目
contentDetailsduration, dimension, definition, caption, licensedContent, contentRating, projection
fileDetails投稿主のみアクセス可
id動画 ID
liveStreamingDetailsactualStartTime, scheduledStartTime, concurrentViewers, activeLiveChatId
localizations
playerembedHtml
processingDetails投稿主のみアクセス可
recordingDetails
snippetpublishedAt, channelId, title, description, thumbnails, channelTitle, tags, categoryId, liveBroadcastContent, localized, defaultAudioLanguage
statisticsviewCount, likeCount, dislikeCount, favoriteCount, commentCount
statusuploadStatus, privacyStatus, license, embeddable, publicStatsViewable, madeForKids
suggestions投稿主のみアクセス可
topicDetailstopicCategories

チャンネル情報や動画情報をリクエストする際、一度に指定できる id の数は 50 までの様です。

Mac で Python 仮想環境に Django をインストールしたい

Python の仮想環境を作る

仮想環境を作成したいディレクトリへ行き、下記のコマンドを実行します。例として「sample_virtual_environment」という仮想環境を作ります。

 python3 -m venv sample_virtual_environment

すると下記の様に Python の実行に必要なファイルやフォルダが一式作成されます。

これで仮想環境の作成は完了です。実際に仮想環境「sample_virtual_environment」を起動するには下記を実行します。

% cd sample_virtual_environment/bin
% source activate

下記の様にカッコの中に仮想環境の名前が表示されると思います。

(sample_virtual_environment) %

仮想環境から出たい場合は「deactivate」を実行します。

(sample_virtual_environment) % deactivate
%

Django をインストールする

仮想環境で Django をインストールするには、仮想環境を activate した状態で下記を実行します。

(sample_virtual_environment) % pip install django

下記のようなログが表示されて最後の方に「Successfully installed」と出ていれば成功です。

(sample_virtual_environment) % pip install django
Collecting django
  Downloading https://files.pythonhosted.org/packages/b8/6f/9a4415cc4fe9228e26ea53cf2005961799b2abb8da0411e519fdb74754fa/Django-3.1.7-py3-none-any.whl (7.8MB)
     |████████████████████████████████| 7.8MB 337kB/s 
Collecting asgiref<4,>=3.2.10 (from django)
  Downloading https://files.pythonhosted.org/packages/89/49/5531992efc62f9c6d08a7199dc31176c8c60f7b2548c6ef245f96f29d0d9/asgiref-3.3.1-py3-none-any.whl
Collecting sqlparse>=0.2.2 (from django)
  Downloading https://files.pythonhosted.org/packages/14/05/6e8eb62ca685b10e34051a80d7ea94b7137369d8c0be5c3b9d9b6e3f5dae/sqlparse-0.4.1-py3-none-any.whl (42kB)
     |████████████████████████████████| 51kB 9.6MB/s 
Collecting pytz (from django)
  Downloading https://files.pythonhosted.org/packages/70/94/784178ca5dd892a98f113cdd923372024dc04b8d40abe77ca76b5fb90ca6/pytz-2021.1-py2.py3-none-any.whl (510kB)
     |████████████████████████████████| 512kB 8.1MB/s 
Installing collected packages: asgiref, sqlparse, pytz, django
Successfully installed asgiref-3.3.1 django-3.1.7 pytz-2021.1 sqlparse-0.4.1
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(sample_virtual_environment) %

以上で Django のインストールは完了です。続けて Django プロジェクトそして Django アプリケーションの作成はこちらの記事へ。