実現したいこと
List All Customer Reviews for an App(アプリのすべての顧客レビューをリストする)
のデータを、BigQueryテーブルに格納したいが、エラーが出てしまうので解決したい。
発生している問題・分からないこと
特殊文字が含まれてることによる文字化けが原因かと仮定し、下記検証。
他原因は現状思いついていません。
① 特殊文字を削除したい。
→いろんな場所に .decode('utf-8','replace') を付与して試したが、意図した状態にならない。
また、.decode('cp932','replace') に敢えて変換し特殊文字が消えることを期待したがこちらもうまくいかず。
② 出力時に 'Content-Type': 'text/html; charset=utf-8' にしたい。
→現状、バケットのファイルのページでContent-Type欄に
text/html; charset=utf-8
を手入力する必要がある。
※補足:
API経由でデータをバケットに格納すること自体は出来ている。
<実装状況>
Apple Developer API から連携
→ Google Cloud Function で読み込み
→ Google Cloud Storage に保存
→ Google BigQuery Studio でテーブルに書き出し ★読み込み不可
エラーメッセージ
error
1Error while reading data, error message: CSV table encountered too many errors, giving up. Rows: 37; errors: 100. Please look into the errors[] collection for more details. File: gs://[バケット名]/[ファイル名].csv.gz
該当のソースコード
import base64 import logging, os, sys, re import pprint import datetime import urllib.request,urllib.error from google.cloud import storage import jwt import time from google.cloud import secretmanager from google.oauth2 import service_account import json # JWTトークンの生成 ### 省略 ### # APIからレポートを取得 def __get_reports(token,date_str=None): base_url = 'https://api.appstoreconnect.apple.com/v1/apps/xxxxxxxx/customerReviews' #ダミー値 vendor_number = xxxxxxxx #ダミー値 if not date_str: jst = datetime.timezone(datetime.timedelta(hours=+9), 'JST') date_str = (datetime.datetime.now(jst) - datetime.timedelta(days=2)).strftime('%Y-%m-%d') path_parameters = { "id" : xxxxxxxx #ダミー値 } query_parameters = { } url = base_url headers = {'Authorization': 'Bearer ' + token,'Accept': '*/*'} req = urllib.request.Request('{}?{}'.format(url, urllib.parse.urlencode(query_parameters)), headers=headers) try: with urllib.request.urlopen(req) as res: content = res.read() print("done") #デバッグ code = 200 except (urllib.error.HTTPError, urllib.error.URLError) as e: logging.error("Error occered in urllib.request.Request().\n code: " + str(e.code) + \ "\n reason: " + e.reason) code = e.code content = e.reason print("error") #デバッグ return (code, content, date_str) # Cloud Storageにレポートを格納 def __write_to_gcs(content,filename): storage_client = storage.Client() bucket_name = 'xxxxxxxx' #ダミー値 bucket = storage_client.get_bucket(bucket_name) blob = bucket.blob(filename) blob.upload_from_string(content) def get_apple_reports(request): token = __get_apple_store_connect_api_token() vendor_number = 'xxxxxxxx' date_str = None (code, content, date_str) = __get_reports(token, date_str) filename = date_str + '.csv.gz' __write_to_gcs(content,filename) return (None,200,None) def get_customer_reviews(event, context): request = {"args": {"date_str": None}} get_apple_reports(request)
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
取り込めない理由はエラー文から断定はできない。
仮説通り特殊文字のせいだとするならば、具体的に引っかかっていると推測している文字は「●」で、出力結果に残ってしまう。
恐らくこの文字↓
https://lets-emoji.com/black-circle-emoji/
補足
print("done") の代わりに、
print(res.msg.as_string()) や print(ascii(content))を入れた結果のログ:
{ insertId: "***" logName: "projects/***/logs/cloudaudit.googleapis.com%2Factivity" operation: { first: true id: "operations/***" producer: "cloudfunctions.googleapis.com" } protoPayload: { @type: "type.googleapis.com/google.cloud.audit.AuditLog" authenticationInfo: { principalEmail: "***@***" } authorizationInfo: [ 0: { granted: true permission: "cloudfunctions.functions.update" permissionType: "ADMIN_WRITE" resource: "projects/***" resourceAttributes: { }}] methodName: "google.cloud.functions.v1.CloudFunctionsService.UpdateFunction" request: { @type: "type.googleapis.com/google.cloud.functions.v1.UpdateFunctionRequest" function: { availableMemoryMb: 2048 dockerRegistry: "CONTAINER_REGISTRY" entryPoint: "***" eventTrigger: { eventType: "google.pubsub.topic.publish" resource: "projects/***" } ingressSettings: "ALLOW_INTERNAL_ONLY" maxInstances: 1 name: "projects/***" runtime: "python311" serviceAccountEmail: "***@***" sourceUploadUrl: "https://storage.googleapis.com/***" timeout: "120s" } updateMask: "sourceUploadUrl" } requestMetadata: { callerIp: "***" callerSuppliedUserAgent: "***" destinationAttributes: { } requestAttributes: { auth: { } time: "2024-04-23T05:07:04.513356Z" }} resourceLocation: { currentLocations: [ 0: "***" ]} resourceName: "projects/***" serviceName: "cloudfunctions.googleapis.com" } receiveTimestamp: "2024-04-23T05:07:04.756380944Z" resource: { labels: { function_name: "***" project_id: "***" region: "***" } type: "cloud_function" } severity: "NOTICE" timestamp: "2024-04-23T05:07:03.340489Z"}
あなたの回答
tips
プレビュー