feat(webscrape-bank): added code to webscrape my bank, api is next
This commit is contained in:
commit
b8552eaefa
6 changed files with 3974 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# PERSONAL INFO
|
||||
.env
|
||||
**/My-Finances*
|
||||
notes
|
||||
**/*qfx
|
||||
|
||||
# Others
|
||||
node_modules/
|
||||
32
actual-api/src/index.js
Normal file
32
actual-api/src/index.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
require("dotenv").config();
|
||||
let api = require("@actual-app/api");
|
||||
|
||||
// Constants
|
||||
const ACTUAL_URL = process.env.ACTUAL_URL
|
||||
const ACTUAL_PASSWORD = process.env.ACTUAL_PASSWORD
|
||||
const ACTUAL_SYNC_ID = process.env.ACTUAL_SYNC_ID
|
||||
const ACTUAL_CHECKING_ID = process.env.ACTUAL_CHECKING_ID
|
||||
|
||||
(async () => {
|
||||
await api.init({
|
||||
dataDir: "./",
|
||||
serverURL: ACTUAL_URL,
|
||||
password: ACTUAL_PASSWORD,
|
||||
});
|
||||
|
||||
console.log("Downloading the Budget Data")
|
||||
await api.downloadBudget(ACTUAL_SYNC_ID);
|
||||
|
||||
console.log("Getting Account Info")
|
||||
let accountInfo = await api.getAccounts()
|
||||
console.log(accountInfo)
|
||||
|
||||
function inspectBankFile() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//await api.shutdown();
|
||||
|
||||
|
||||
})();
|
||||
3817
package-lock.json
generated
Normal file
3817
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
18
package.json
Normal file
18
package.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "transaction-sync",
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"actual": "node actual-api/src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actual-app/api": "^26.1.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"dotenv": "^17.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.2",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-import": "^2.32.0"
|
||||
}
|
||||
}
|
||||
99
webscrape-bank/src/extract.py
Normal file
99
webscrape-bank/src/extract.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
from playwright.sync_api import Playwright, sync_playwright, Page
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
from time import sleep
|
||||
|
||||
load_dotenv()
|
||||
|
||||
BANK_USER = os.getenv("BANK_USER")
|
||||
BANK_PASS = os.getenv("BANK_PASS")
|
||||
LOGIN_LINK = os.getenv("LOGIN_LINK")
|
||||
ACCOUNT_LINK = os.getenv("ACCOUNT_LINK")
|
||||
|
||||
def main(playwright: Playwright) -> None:
|
||||
browser = playwright.chromium.launch(headless=False)
|
||||
context = browser.new_context()
|
||||
|
||||
page = context.new_page()
|
||||
page.goto(LOGIN_LINK)
|
||||
page.locator("#username").click()
|
||||
page.locator("#username").fill(BANK_USER)
|
||||
page.locator("#password").click()
|
||||
page.locator("#password").fill(BANK_PASS)
|
||||
page.get_by_role("button", name="Login", exact=True).click()
|
||||
|
||||
# Wait a little bit
|
||||
page.wait_for_load_state()
|
||||
page.get_by_role("button", name="Text").click()
|
||||
page.get_by_test_id("text-field").click()
|
||||
|
||||
# Bank prompts 2FA (hopefully only once)
|
||||
two_fac = input("2FA Code: ")
|
||||
|
||||
page.get_by_test_id("text-field").fill(two_fac)
|
||||
page.get_by_test_id("private-button").click()
|
||||
|
||||
# Wait for everything to load...
|
||||
page.wait_for_timeout(5000)
|
||||
|
||||
# We should be at the home page here
|
||||
download_file(page)
|
||||
|
||||
|
||||
def switchingForever(page: Page):
|
||||
print("Switching to not get timed out!")
|
||||
page.goto(ACCOUNT_LINK)
|
||||
|
||||
count = 0
|
||||
|
||||
while (count < 12):
|
||||
page.wait_for_timeout(5000)
|
||||
page.get_by_role("link", name="Cards").hover()
|
||||
page.get_by_role("link", name="Activate Card").click(timeout=0)
|
||||
sleep(300)
|
||||
page.get_by_role("link", name="My Accounts").click(timeout=0)
|
||||
count = count + 1
|
||||
print("Count updated: " + str(count))
|
||||
|
||||
download_file(page)
|
||||
|
||||
|
||||
def download_file(page: Page):
|
||||
print("Going to download a new QFX File")
|
||||
page.goto(ACCOUNT_LINK)
|
||||
|
||||
page.locator('iframe[title="Next Gen Home Page"]').content_frame.get_by_test_id(
|
||||
"com.ncr.dbk.olb.widgets.my-accounts"
|
||||
).get_by_test_id("feature-link").click()
|
||||
|
||||
page.wait_for_timeout(5000)
|
||||
|
||||
page.locator("#ncr-la-chat-win-notif-close path").click()
|
||||
|
||||
page.locator(
|
||||
'iframe[title="NextGen account history page"]'
|
||||
).content_frame.get_by_role("button", name="Download Transactions Button").click()
|
||||
|
||||
with page.expect_download(timeout=0) as download_info:
|
||||
page.mouse.wheel(0, 70)
|
||||
|
||||
page.locator(
|
||||
'iframe[title="NextGen account history page"]'
|
||||
).content_frame.get_by_role("menuitem", name="Export QFX").dblclick()
|
||||
|
||||
|
||||
download = download_info.value
|
||||
|
||||
download.save_as("./test.qfx")
|
||||
|
||||
print("Downloaded!")
|
||||
|
||||
switchingForever(page)
|
||||
|
||||
# context.close()
|
||||
# browser.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
with sync_playwright() as playwright:
|
||||
main(playwright)
|
||||
0
webscrape-bank/src/main.py
Normal file
0
webscrape-bank/src/main.py
Normal file
Loading…
Add table
Add a link
Reference in a new issue