iT邦幫忙

0

取得兆豐銀行歷史匯率資料

php
WQ 2019-06-03 11:21:132464 瀏覽

想抓的資料來源
https://wwwfile.megabank.com.tw/other/bulletin02_09.asp

因有需求想抓取上述資料來源的匯率,原先認為抓取每日結匯的匯率資料
http://rate.megabank.com.tw/bulletin02_02.asp ,(抓這個沒問題)
但它的結匯的數據並不等於歷史匯率數據,此時已經霧裡看花了....
藉由想取得的資料來源進行來源查找(F12查得另一資料來源),得到了下列網址
https://ebank.megabank.com.tw/global2/rs/rs03/PRS3001.faces
分析後得知網址需先取得ptoken= & javax.faces.ViewState= 的值(這部份也完成了),
但仍然不能取得歷史匯率資料,我有試著先手動開啟網頁查詢一次,並且不關視窗,就可以取得資料,是否還有漏了什麼動作或有什麼機制使得資料無法自動截取呢?
請各位先進指教一下,謝謝。

<?php
include('simple_html_dom.php');

// get DOM from URL or file
//$base = 'https://wwwfile.megabank.com.tw/other/bulletin02_09.asp';
$base = "https://ebank.megabank.com.tw/global2/rs/rs03/PRS3001.faces";
$curl = curl_init();
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_URL, $base);
curl_setopt($curl, CURLOPT_REFERER, $base);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

$str = curl_exec($curl);
curl_close($curl);

// Create a DOM object
$html = new simple_html_dom();

// Load HTML from a string
$html->load($str);

// Get ptoken & javax.faces.ViewState
preg_match_all ('/action="(.*)"/U', $html, $pat_array); 
$textFieldValue = $html->find('[id="javax.faces.ViewState"]',0)->value;
// NewURL
$newurl="https://ebank.megabank.com.tw".$pat_array[1][0]."&main=main&main%3Acurrency=03&typeGrp=LST&main%3AstartDate=2019%2F05%2F27&main%3AendDate=2019%2F05%2F31&main%3AdownloadType=TEXT&autoDisabled%3Amain%3Aj_id31=AutoDisabled%3AClicked&submitTrigger=&autoDisabled%3Amain%3AfileDownload=&autoDisabled%3Amain%3Aj_id32=&main%3Ahidstartdate=&main%3Ahidenddate=&javax.faces.ViewState=".$textFieldValue;

echo $newurl;

?>
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
dragonH
iT邦超人 5 級 ‧ 2019-06-03 21:21:39
最佳解答

我把 header 跟 form data

都塞到 postman 也是無法

可能是有什麼防範機制吧

不過他看起來沒有用 captcha 來防

就懶得去研究了

直接用最近在玩的 Puppeteer 來爬

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://ebank.megabank.com.tw/global2/rs/rs03/PRS3000.faces');
  const dropDown = await page.select('#main\\:currency', '01');
  const searchBtn = await page.click('#main\\:j_id31');
  await page.waitForNavigation();
  const header = await page.evaluate(() => {
    const tds = Array.from(document.querySelectorAll('.head_td'));
    return tds.map(td => td.innerHTML.trim());
  });
  const values = await page.evaluate(() => {
    const tds = Array.from(document.querySelectorAll('.con_td'));
    return tds.map(td => td.innerHTML.trim());
  });
  const result = header
    .map((data, index) => { return { title: header[index], value: values[index]}})
    .filter((data) => data.title !== '');
  console.log(result);
  await browser.close();
})();

Result

[ { title: '幣  別', value: '美金[USD]' },
  { title: '查詢起日', value: '2019/06/01' },
  { title: '查詢迄日', value: '2019/06/03' },
  { title: '日期', value: '2019/06/03' },
  { title: '即期買匯', value: '31.4400' },
  { title: '現金買匯', value: '31.1000' },
  { title: '即期賣匯', value: '31.5400' },
  { title: '現金賣匯', value: '31.7700' } ]

以上是用 node.js

php好像也有相關套件能用

稍微改一下應該就可以了

看更多先前的回應...收起先前的回應...
WQ iT邦新手 2 級 ‧ 2019-06-04 08:11:08 檢舉

感謝您的方向,看來得試試NODE.JS 或 Puppeteer for PHP

dragonH iT邦超人 5 級 ‧ 2019-06-04 09:06:29 檢舉

也不一定就是

只是用不同方式爬會比較方便

例如這個

看起來跟 Puppeteer 很像

你可以試試看

WQ iT邦新手 2 級 ‧ 2019-06-04 09:35:16 檢舉

真給力,就把這些RUN一遍。

WQ iT邦新手 2 級 ‧ 2019-06-04 11:32:19 檢舉

輸入日期我使用page.type會有錯誤,是我的認知有誤嗎?

await page.type('#main\\:startDate', '2019/06/03');
await page.type('#main\\:endDate', '2019/06/03');
dragonH iT邦超人 5 級 ‧ 2019-06-04 11:53:57 檢舉

他是用 querySelector

所以:那邊要兩個 \ 唷

另外剛試了一下

如果要輸入日期

還要先把 input 清空

跟一般操作一樣

  await page.evaluate( () => {
    document.getElementById("main:startDate").value = '';
    document.getElementById("main:endDate").value = '';
  });
  const enterStartDate = await page.type('#main\\:startDate', '2019/06/03');
  const enterEndDate = await page.type('#main\\:endDate', '2019/06/03');

可以用 page.screenshot 來擷取操作dom的情況

 await page.screenshot({path: 'screenshot.png'});

https://ithelp.ithome.com.tw/upload/images/20190604/20117259YefYxvEMYE.png

2
wwx
iT邦好手 1 級 ‧ 2019-06-04 09:41:08
WQ iT邦新手 2 級 ‧ 2019-06-04 11:33:12 檢舉

謝謝WWX的答案,也是可以使用,小弟也會一併測試!!

我要發表回答

立即登入回答