Yahoo Financeのmyポートフォリオから銘柄コードをスクレイピングする
Yahooファイナンスのポートフォリオ機能を使って過去取引した銘柄やWatch銘柄を管理しています。
YFでは1pfあたり管理できる銘柄数が最大50なので、監視銘柄が増えるほど新規に作らないといけません。
私は、例えば四季報を読んで、気になる銘柄をNotepadやiPhoneでメモして、"四季報18年春_1"みたいなポートフォリオを作って管理するやり方をしています。
これだとポートフォリオ自体の数が増えると、いざ分析でコードだけキーに使いたい時に、いちいちコピペしていくのがかなり面倒です。(私の場合、直近だと15pfあります)、
そこで、Nightmare.jsを使い、ユーザの全ポートフォリオから一括で銘柄コードを取得するjavascriptを書きました。
- 適当にfolderを作って下記のソースからpackage.jsonを作成
- そのfolder下で.evn.jsonを作成。YahooのログインID、パスワードを書く
- npm install
- node run.js false してやれば、スクレイピング結果を反映したdata.jsonが作成されるはずです。
//run.js var env = require('gulp-env'); var Nightmare = require('nightmare'); var vo = require('vo'); const {promisify} = require('util'); var fs = require("fs"); const writeFileAsync = promisify(fs.writeFile); const FAKE_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/41.0.2228.0 Safari/537.36'; const YAHOO_FINANCE_URL = 'http://finance.yahoo.co.jp/' const JSON_FILE = './data.json' env({ file: './.env.json' }); let nightmare = Nightmare({show: true}); const YahooFinanceLogin = (nightmare) => { return nightmare .useragent(FAKE_USER_AGENT) .goto(YAHOO_FINANCE_URL) .click('ul.portFolioIn li.help a') .wait('div#idWrap') .type('input#username', process.env.USER_ID) .click('button#btnNext') .wait(2000) .type('input#passwd', process.env.PASSWORD) .wait(1000) .click('#btnSubmit') .wait(3000) .wait('span.portFolio') } const getIdxOfPortfolio = (nightmare, portFolioName) => { return nightmare.evaluate((portFolioName) => { return Array.from(document.querySelectorAll('ul.portFolioIn > li')).map((e) => { return e.textContent }).indexOf(portFolioName) }, portFolioName).then((idx) => { return idx }); } const getListOfPortfolios = (nightmare) => { return nightmare.wait('ul.portFolioIn').evaluate(() => { return Array.from(document.querySelectorAll('ul.portFolioIn > li')).map((e, idx) => { return {'name': e.textContent, 'idx': idx} }); }) } const getSharesFromPortfolio = (nightmare, idxOfPortfolio) => { return nightmare .click('ul.portFolioIn > li:nth-child(' + idxOfPortfolio + ') a') .wait('table.smallText') .wait(500) .evaluate(() => { return Array.from(document.querySelectorAll('div.pfListView table tbody#tbotyPortfolioList > tr > td:nth-child(2)')).map((e) => { return e.innerText.replace('\n', '') }); }) } const writeToJsonFile = (o) => { return writeFileAsync(JSON_FILE, JSON.stringify(o), (err) => { if (err) { console.error(err); return; }; console.log("File has been created"); }); } vo(function* () { const testRun = process.argv[process.argv.length-1];; let nightmare = Nightmare({show: false}) yield YahooFinanceLogin(nightmare); //Login let code = ''; let jsonObj = []; if (testRun) { code = yield getSharesFromPortfolio(nightmare, 1) } else { let listOfPortfolios = yield getListOfPortfolios(nightmare); for (var i = 0, len = listOfPortfolios.length; i < len; i++) { let codes = yield getSharesFromPortfolio(nightmare, listOfPortfolios[i].idx + 1) console.log('-----') console.log(listOfPortfolios[i].name); console.log('-----') var t = {'name': listOfPortfolios[i].name, 'code': codes} jsonObj.push(t); } yield writeToJsonFile(jsonObj); } yield nightmare.end(); if (testRun) { return code } else { return jsonObj } })((err, result) => { if (err) return console.log(err); console.log(result); });
//package.json { "name": "yahoofinancenightmare", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "testRun": "node run.js true", "prd": "node run.js false" }, "author": "", "license": "ISC", "devDependencies": { "argv": "0.0.2", "csv-write-stream": "^2.0.0", "fs": "0.0.1-security", "gulp-env": "^0.4.0", "nightmare": "^2.10.0", "vo": "^4.0.2" } }
//.env.json { "USER_ID": "YOUR_USER_ID", "PASSWORD": "YOUR_PASSWORD" }