みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
Filemakerserver18(WindowsServer2016) Filemakerpro19(Windows10)で運用しています
今回とあるWEBサイトにある価格相場情報(テーブル)を毎日取り込む必要が出てきました
※今まではGoogleスプレッドシートのIMPORTHTML関数を使って該当するテーブルを表示していましたがFilemakerで利用することになりました
URLから挿入でFilemaker上のフィールドにhtmlテキストで取り込みましたが、その中のテーブルの内容をFilemakerのテーブルにインポート(?)したいのですがその方法が分からなくて四苦八苦しています
取込んだHTMLからやりたいことは以下です
1.2番目に出現する<table>の内容をFilemaker上のテーブルにデータ取込を行いたい
2.取り込む内容は<tboby>から</tbody>に記述されている<tr><th><td>の各要素
3.<table>の構成は常に一定で10レコード5フィールドになっています(サイズ、価格1、価格2、価格3、価格4の5フィールド)
4.Filemaker側にもその5フィールドと取得日時の1フィールドをもつ「相場テーブル」を作成してあります
過去記事も探してみましたが分かりませんでした
上記のやり方をご教授いただけないでしょうか?
よろしくお願いします
Offline
フィールド:TAG に以下例のようなTABLEタグがある場合、下記計算式でCSVのようなデータの取得が可能です。※各行行末の , が余分
検証少なめです。TAGによってはキチンと動作しないかも...
例:
フィールド:TAG
<tbody>
<tr><th>A</th><th>B</th><th>C</th></tr>
<tr><td>データA1</td><td>データB2</td><td>データC3</td></tr>
<tr><td>データA2</td><td>データB2</td><td>データC2</td></tr>
</tbody>
式
Let([
TEXT=TAG
;TEXT=Substitute ( TEXT ; ¶ ; "" )
];
Evaluate (
Substitute ( Quote ( TEXT )
; ["</tr>" ; Char ( 10 )]
; ["<th" ; "\\\"\" & Evaluate ( Let ( _ = \""]
; ["</th" ; "\\\",\" & Evaluate ( Let ( _ = \""]
; ["<td" ; "\\\"\" & Evaluate ( Let ( _ = \""]
; ["</td" ; "\\\",\" & Evaluate ( Let ( _ = \""]
; ["<" ; "\" & Evaluate ( Let ( _ = \""]
; [">" ; "\" ; \"\" ) ) & \""]
)
)
)
結果
"A","B","C",
"データA1","データB2","データC3",
"データA2","データB2","データC2",
別の方法としては、テーブルタグを CSV や JSON に変換できるJavaScriptライブラリを探してWEBビューア経由で処理するとか...
Offline
>TAGによってはキチンと動作しないかも
そこなんですよ。何の相場かしらないけど、どうせならHTMLでなくちゃんとしたAPIで取得した方が確実ですが...相手次第で急に動かなくなったりするので。
他の方法は、Excelのテーブルソース機能とかも使えるかもね
2番目に出現する<table>~</table>のみを抽出するにはどうすればよいでしょうか?
Offline
Position()で何回目、の指定ができますよ
1テキストのタグ内文字列の切り出しをする関数
も参考にしてみてください。[table]や[tag]がネスとされていることはまずないでしょうが、ネストに対応した[tag]を切り出す式です。
While (
[
txt = html ;
tag0 = "<p>" ;
num = n ;
tag1 = Replace ( tag0 ; 2 ; 0 ; "/" ) ;
pos0 = Position ( txt ; tag0 ; 1 ; num ) ;
cnt = 0 ;
txt1 = tag0
] ;
PatternCount ( txt1 ; tag0 ) ≠ PatternCount ( txt1 ; tag1 ) ;
[
cnt = cnt + 1 ;
pos1 = Position ( txt ; tag1 ; pos0 ; cnt ) + Length ( tag1 ) ;
txt1 = Middle ( txt ; pos0 ; pos1 - pos0 )
] ;
txt1
)
Last edited by Shin (2021-03-05 12:13:20)
Offline
こちらのカンジが値の取得がしやすいかも。
式
Let([
TEXT=名称未設定::TAG
;TEXT=Substitute ( TEXT ; [¶ ; ""]; ["<tr>" ; "[" ]; ["</tr>" ; "]" & Char ( 10 ) ] )
;val=
Evaluate (
Substitute ( Quote (Quote ( TEXT ) )
; ["<th" ; "\\\"\" & Evaluate ( Let ( _ = \""]
; ["</th" ; "\\\",\" & Evaluate ( Let ( _ = \""]
; ["<td" ; "\\\"\" & Evaluate ( Let ( _ = \""]
; ["</td" ; "\\\",\" & Evaluate ( Let ( _ = \""]
; ["<" ; "\" & Evaluate ( Let ( _ = \""]
; [">" ; "\" ; \"\" ) ) & \""]
)
)
;val=Replace ( val ; 1 ; 1 ; "" )
;val=Replace ( val ; Length ( val ) ; 1 ; "" )
;val=Substitute ( val ; ",]" & Char ( 10 ) ; "]¶" )
];
val
)
結果
["A","B","C"]
["データA1","データB2","データC3"]
["データA2","データB2","データC2"]
結果が $result に入っているとして、
JSONGetElement ( GetValue ( $result ; 2 ) ; 0 )
とすれば、2行目の最初のデータ "データA1" が取得できます。
Offline
ありがとうございます。
1.Shinさんのやり方で2番目に出現する<table>の内容の抽出に成功
2.qb_dpさんの式で出てきた結果が改行と8文字TABは残っているもののデータは取り出せています
3JSONの結果は以下のエラーになりました
? * Line 1, Column 4
Syntax error: value, object or array expected.
* Line 1, Column 1
A valid JSON document must be either an array or an object value.
2.の結果からTABコードと余分な改行コードを取り除けばよいのでは、、、と思いますがやり方が分かりません
また、出てきた結果をよく見ると<thead>部分はダブルクォーテーションで囲まれていることが分かりました
1.の手順では2番目に出現した<table>の内容が抽出されているので<thead>部分も抽出されているためqb_dpさんに提示した条件と変わってしまっています
併せてご教授をお願いいたします
Offline
私の式は、元のTABLEタグ変わると破綻します。
Shinさんの式で一つづつ値を取得するのがよいかも。
Offline
その後2番目の<tbody>を取り出せばよいことに気づいてやりましたが下記のようにTABや改行が入ります
改行の削除は分かるのですがTABを削除するのはどうすればよいでしょうか
Substitute(○○;CHR(9);"")かと思いましたがCHR(9)は受け付けてくれませんでした
Offline
あ、勘違いしてました、、お恥ずかしい
で何とか下記のように抽出することができましたがqb_dpさんの式をどう直せばよいのか悩んでいます
----------------------------------------------------------------------------
<tbody>
<tr>
<th>LL</th>
<td>222</td>
<td>200</td>
<td>±0</td>
<td>194</td>
</tr>
<tr>
<th>L</th>
<td>233</td>
<td>210</td>
<td>±0</td>
<td>204</td>
</tr>
<tr>
<th>M</th>
<td>243</td>
<td>220</td>
<td>±0</td>
<td>214</td>
</tr>
<tr>
<th>MS</th>
<td>248</td>
<td>225</td>
<td>±0</td>
<td>219</td>
</tr>
<tr>
<th>S</th>
<td>226</td>
<td>205</td>
<td>±0</td>
<td>199</td>
</tr>
<tr>
<th>SS</th>
<td>175</td>
<td>155</td>
<td>±0</td>
<td>149</td>
</tr>
<tr>
<th>特殊高値</th>
<td>-----</td>
<td>232</td>
<td>±0</td>
<td>-----</td>
</tr>
<tr>
<th>特殊安値</th>
<td>-----</td>
<td>97</td>
<td>±0</td>
<td>-----</td>
</tr>
<tr>
<th>市況</th>
<td colspan="4">保合</td>
</tr>
<tr>
<th>入荷量</th>
<td colspan="4">365t</td>
</tr>
</tbody>
----------------------------------------------------------------------------
Offline
提示のTAGなら以前の式でも大丈夫そうです。
一応、新式
Let([
TEXT=Substitute ( 名称未設定::TAG ; [Char(12288) ; Char(32)] ; [Char(9) ; Char(32)] )
;TEXT=While (
[
tag = TEXT
] ;
PatternCount ( tag ; Char(32) & "<" )>0;
[
tag=Substitute ( tag ; Char(32) & "<" ; "<" )
] ;
tag
)
;TEXT=Substitute ( TEXT
; [¶ ; ""]
; ["<tr" ; "[<tr" ]
; ["</tr>" ; "</tr>]" & Char ( 10 ) ]
)
;val=Evaluate (
Substitute ( Quote (Quote ( TEXT ) )
; ["<thead" ; "\" & Evaluate ( Let ( _ = \""]
; ["</thead" ; "\" & Evaluate ( Let ( _ = \""]
; ["<th" ; "\\\"\" & Evaluate ( Let ( _ = \""]
; ["</th" ; "\\\",\" & Evaluate ( Let ( _ = \""]
; ["<td" ; "\\\"\" & Evaluate ( Let ( _ = \""]
; ["</td" ; "\\\",\" & Evaluate ( Let ( _ = \""]
; ["<" ; "\" & Evaluate ( Let ( _ = \""]
; [">" ; "\" ; \"\" ) ) & \""]
)
)
;val=Replace ( val ; 1 ; 1 ; "" )
;val=Replace ( val ; Length ( val ) ; 1 ; "" )
;val=Substitute ( val ; ",]" & Char ( 10 ) ; "]¶" )
];
val
)
Offline
最終目的は、テーブルに新規レコードとして、サイズ、価格1、価格2、価格3、価格4を取り込むんですよね。
ExtractTag ( html ; tag ; number )
While (
[
txt = html ;
tag0 = tag ;
num = number ;
tag1 = Replace ( tag0 ; 2 ; 0 ; "/" ) ;
pos0 = Position ( txt ; tag0 ; 1 ; num ) ;
cnt = 0 ;
txt1 = tag0
] ;
PatternCount ( txt1 ; tag0 ) ≠ PatternCount ( txt1 ; tag1 ) ;
[
cnt = cnt + 1 ;
pos1 = Position ( txt ; tag1 ; pos0 ; cnt ) + Length ( tag1 ) ;
txt1 = Case ( pos0 ; Middle ( txt ; pos0 ; pos1 - pos0 ) ; "" )
] ;
txt1
)
というカスタム関数を定義しておけば、
変数を設定 [ $txt ; 値: ExtractTag ( テーブル::g_html ; "<tbody>" ; 2 ) ]
変数を設定 [ $n ; 値: 1 ]
Loop
新規レコード/検索条件
変数を設定 [ $rec ; 値: ExtractTag ( $txt ; "<tr" ; $n ) ]
フィールド設定 [ テーブル::サイズ ; ExtractTag ( $rec ; "<th" ; 1 ) ]
フィールド設定 [ テーブル::価格1 ; ExtractTag ( $rec ; "<td" ; 1 ) ]
フィールド設定 [ テーブル::価格2 ; ExtractTag ( $rec ; "<td" ; 2 ) ]
フィールド設定 [ テーブル::価格3 ; ExtractTag ( $rec ; "<td" ; 3 ) ]
フィールド設定 [ テーブル::価格4 ; ExtractTag ( $rec ; "<td" ; 4 ) ]
Exit Loop If [ Let ( $n = $n + 1 ; $n > 10 ) ]
End Loop
だけで済みますよ。
Last edited by Shin (2021-05-12 10:42:09)
Offline
qb_dpさん、Shinさんありがとうございます
現在他の案件(Filemakerではない)にかかりっきりでまだ検証できておりませんが、後日報告させていただきます。
少しづつ光が見えてうれしいです
Offline
ExtractTag ( html ; tag ; number )
While (
[
txt = html ;
tag0 = tag ;
num = number ;
tag1 = Replace ( tag0 ; 2 ; 0 ; "/" ) ;
pos0 = Position ( txt ; tag0 ; 1 ; num ) ;
cnt = 0 ;
txt1 = tag0
] ;
PatternCount ( txt1 ; tag0 ) ≠ PatternCount ( txt1 ; tag1 ) ;
[
cnt = cnt + 1 ;
pos1 = Position ( txt ; tag1 ; pos0 ; cnt ) + Length ( tag1 ) ;
txt1 = Middle ( txt ; pos0 ; pos1 - pos0 )
] ;
txt1
)
カスタム関数がうまく働いていないようで、取得した値がそれぞれ
サイズフィールド:<th>LL</th 価格1フィールド:<td>205</td 価格2フィールド<td>227</td 価格3フィールド:<td>199</td
となりhtmlタグの始まりと終わりのタグの最後の>が取り去られたものとなります
どこを直せばよいでしょうか?
Offline
タグを含めて取り出す関数でした。結果を、
Let (
[
t = ExtractTag ( $rec ; "<td" ; 1 ) ;
t = Substitute ( t ;[ "<" ; ¶ ];[ ">" ; ¶ ])
] ;
GetValue ( t ; 3 )
)
という式を通せばいいでしょう。(フィールド設定の中に組み込みます)
変数を設定 [ $txt ; 値: ExtractTag ( テーブル::g_html ; "<tbody>" ; 2 ) ]
変数を設定 [ $n ; 値: 1 ]
Loop
新規レコード/検索条件
変数を設定 [ $rec ; 値: ExtractTag ( $txt ; "<tr" ; $n ) ]
フィールド設定 [ テーブル::サイズ ; GetValue ( Substitute ( ExtractTag ( $rec ; "<th" ; 1 ) ;[ "<" ; ¶ ];[ ">" ; ¶ ]) ; 3 ) ]
フィールド設定 [ テーブル::価格1 ; GetValue ( Substitute ( ExtractTag ( $rec ; "<td" ; 1 ) ;[ "<" ; ¶ ];[ ">" ; ¶ ]) ; 3 ) ]
フィールド設定 [ テーブル::価格2 ; GetValue ( Substitute ( ExtractTag ( $rec ; "<td" ; 2 ) ;[ "<" ; ¶ ];[ ">" ; ¶ ]) ; 3 ) ]
フィールド設定 [ テーブル::価格3 ; GetValue ( Substitute ( ExtractTag ( $rec ; "<td" ; 3 ) ;[ "<" ; ¶ ];[ ">" ; ¶ ]) ; 3 ) ]
フィールド設定 [ テーブル::価格4 ; GetValue ( Substitute ( ExtractTag ( $rec ; "<td" ; 4 ) ;[ "<" ; ¶ ];[ ">" ; ¶ ]) ; 3 ) ]
Exit Loop If [ Let ( $n = $n + 1 ; $n > 10 ) ]
End Loop
でいいかな。
Last edited by Shin (2021-03-15 16:18:45)
Offline
皆様ありがとうございました
思い通りのものができました
qb_dpさんのものについてはどうしてもきれいにhtml成形ができず、JSONのところでエラーを繰り返していたため、最終的にShinさんのご教授のもので完成いたしました
ただカスタム関数の内容についてまだ理解が不十分でただいま勉強中です
WEBで公開されている表(table)をFilemakerに取込み、日付を加えたデータとして履歴保存できるようになりました
これで事務所にある分厚い帳票綴りが1つ減り、それに伴う事務員さんの作業も減りました
本当にありがとうございました
Offline
[ Generated in 0.007 seconds, 7 queries executed - Memory usage: 574.8 KiB (Peak: 611.7 KiB) ]