時には添付ファイルを何らかの方法で管理する必要があります。この記事ではいくつかの概念を取り上げ、後ほど私のgithubにてご自身の好みに合わせて変更可能な複数の例を掲載します。<\/P>
まず始めに、ArcGIS Enterprise (Portal) または ArcGIS Online のサービスにアクセスするには arcgis ライブラリが必要です。まだインストールしていない場合はインストールしてください(ArcGIS Pro をインストールすると含まれていますし、ArcGIS Enterprise の Python にも含まれています)。<\/P>
この最初のセクションでは Portal または ArcGIS Online にアクセスする方法を説明します。<\/P>
#Portal に接続する
PORTAL = GIS("url", "usuario","contraseña")<\/P>
行っている作業によってはトークンを取得する必要がある場合があります。これは主に添付ファイルのURLを確認したいがサービスが公開されていない場合に使用します。<\/P>
token = PORTAL._con.token<\/P>
これでサービスにアクセスできます。arcgis の API は Portal または ArcGIS Online に保存されているオブジェクトにアクセス可能です。そのため、サイトからサービスのURL(黄色と赤のアイコンがあるもの)にアクセスします。(テキストなので引用符で囲みます)<\/P>
servicio = PORTAL.content.get('item id')<\/P>
この部分にアクセスすると、問い合わせているサービスが持つ異なるレイヤーやテーブルを見ることができます。したがって、レイヤーまたはテーブルのインデックス番号を指定する必要があります。ここで説明しておきたいのは、例えば地理的エンティティとテーブルがある場合、両方ともインデックス0になります。これはシステムがサービス内のレイヤーリストとテーブルリストとして検出するためです。つまり、レイヤー1つとテーブル1つの場合、それぞれインデックス0です。もしレイヤー2つとテーブル1つの場合、レイヤーは0と1、テーブルは0となります。この点で混乱させてしまったらすみません(笑)。<\/P>
パラメータ化するために私は次のようにしました:<\/P>
num_capa=int(indice)<\/P>
注:これは数値データなので単純に値を書きます。<\/P>
前述したようにレイヤーやテーブルが存在する可能性があります。このように添付ファイルもレイヤーかテーブルのどちらかに存在することがあり、そのためツールに次のようなコードを追加しました:<\/P>
tipo="ここに capa または tabla と書く"
if tipo=="capa":
capa=(servicio.layers)[num_capa]
elif tipo=="tabla":
capa =(servicio.tables)[num_capa]<\/P>
URL を構築するために、Esri の API 自体が取得方法を示していますが、それはテキストではなくオブジェクトとして返すので、python の re ライブラリを使って次のようにしました:<\/P>
cap_url=str(re.findall('htt.*'+str(num_capa), str(capa)))
cap_url=str(cap_url)[2:-2]<\/P>
こうしてオブジェクトを文字列(テキスト)に変換します。<\/P>
次に、添付ファイルを保存するフォルダを特定します。
carpeta=r"希望するフォルダのパス"<\/P>
もう一つ使うパラメータは空のテキストフィールドで、そこに添付ファイルが保存される場所のパスを格納します。これによって pandas の dataframe でパラメータ化でき、以下のような処理を行います:<\/P>
sdf = capa.query(where="フィールド名"+" IS NULL").sdf<\/P>
こうしてクエリはそのフィールドが空のものだけを対象とします。<\/P>
その後、編集内で含めるレコードをキャプチャする空リストを作成します。これは後で非常に重要になります。このリストにデータを追加し編集メソッドへ送ることができるからです。行っている作業によります。<\/P>
elementos_a_actualizar = []<\/P>
さて、添付ファイルがあるレイヤーまたはテーブルを反復処理します。<\/P>
#dataframe を通じて反復処理する
for index, row in sdf.iterrows():
objID=str("objectid を含むフィールド")
Attachments = capa.attachments.get_list(oid=objID)<\/P>
同じ反復内で if 文を置きました。前述した通り Attachments はリストとして作成されますので、リストの特徴として要素数を数えることができます。そして if 文はこのリストの長さが0より大きい場合のみ処理を行うことで、添付ファイル付きデータのみ扱うことを二重に保証しています。<\/P>
if len(Attachments)>0:<\/P>
この条件内でメインレイヤーの各 ObjectId に対応する添付ファイルを反復処理します:<\/P>
for k in range(len(Attachments)):
attachmentId = Attachments[k]['id']
attachmentName = Attachments[k]['name']
img_url = cap_url+"\/{0}\/attachments\/{1}".format(objID,attachmentId)+"?token="+token
fileName = os.path.join(carpeta, attachmentName)<\/P>
ご覧の通り、添付ファイルの Id と名前を取得し、それらを先ほど取得した URL とレイヤーまたはテーブルの objectid および添付ファイル Id と連結しています。こうして各添付ファイル固有の URL が得られます。<\/P>
またこれによって先ほど指定したフォルダパスと添付ファイル名も連結可能です。<\/P>
ここで少し工夫できます。この例ではシステムが指定されたフォルダ内に同じ名前の添付ファイルが既にダウンロードされているかどうか判別し、その場合は再度ダウンロードしないようにしています。しかし各要素ごとにフォルダを作成し、その中に該当レコードの全添付ファイルをダウンロードさせることも可能です。この例ではファイル作成用ですが、別途 github の descarga adjuntos スクリプトでフォルダ作成方法も示しています。<\/P>
さて、ここから添付ファイル存在チェック部分です:<\/P>
existe_archiv=os.path.exists(fileName)
if existe_archiv is True:
arcpy.AddMessage("ダウンロードしない")
else:
arcpy.AddMessage("ShapeFile をダウンロード中 " + attachmentName)<\/P>
ここでは os と arcpy ライブラリを使用しています。os は指定フォルダ内でファイル存在有無チェック用であり、この部分で arcpy は ArcGIS 内部へのメッセージ表示用です(もし使わない場合は arcpy.AddMessage を print に置き換え可能です)。<\/P>
これで URL があれば添付ファイルをダウンロードできます。<\/P>
try:
""""""""""""""""""""""""""""""
{} arcpy.AddMessage("ShapeFile の URL を取得中")
{} request=urllib.request.urlretrieve(img_url)
{} req = requests.get(img_url)
{} file = open(fileName, 'wb')
{} for chunk in req.iter_content(100000):
{} file.write(chunk)
{} file.close()
&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; リストに0より多い要素がある場合に戻すように要求していました) データをキャプチャして空のリストに追加するメソッドを使用します。<\/P>
#フォルダのアドレスフィールドを更新する
seleccion=capa.query(where="objectidフィールド"+"="+objID)
elem_actualizar=(seleccion.features[0])
elem_actualizar.attributes["フィールド名"]=str(fileName)<\/P>
添付ファイルがあり、アドレスフィールドが空のレコードをキャプチャして追加します
elementos_a_actualizar.append(elem_actualizar)<\/P>
このメソッドで空のリストにデータを追加した後、このリストを使って要素を編集します。これはdataframeのイテレーションの外側、つまりすべての外側で行います。<\/P>
capa.edit_features(updates=elementos_a_actualizar)<\/P>
ご覧の通り、updatesは先に指定した空のリストと同じです。<\/P>
以上です。私のGitHubにはいくつか例があり、添付ファイルをダウンロードしてサービスから削除したり、単にダウンロードしたり、別の場合にはシェープファイルの添付ファイルをダウンロードして新しいエンティティとして別のサービスに添付したりしています。後ほど詳しく説明できます。<\/P>
もう一つ非常に重要なことは、添付されているtoolboxはバージョン3以降用であり、2.9未満のバージョンの場合はtoolboxを設定する必要があります。そのためスクリプトも添付してカスタマイズできるようにしています。ここにリンクがあります。これは2.9未満のバージョンでツールを設定するための簡単なガイドです。<\/STRONG><\/P>お役に立てれば幸いです。<\/P> <\/P>