RPA-verktyg – Wiki
Referensdokumentation för det interna RPA-verktyget (Playwright + webbaserad
flödesbyggare). Öppna den här sidan lokalt i en webbläsare när du bygger
flöden. Se README.md för installation och kom-igång-instruktioner
– den här sidan är en djupare referens över alla stegtyper, villkor och
mekanismer.
Översikt
Ett flöde är en JSON-fil (data/flows/<namn>.json) i
grafform: {"format":"graph", "nodes":[…], "edges":[…],
"start":"<nod-id>"}. Varje nod har ett
id, en type och typ-specifika fält (platt – ingen
nästling). Kanterna bestämmer körordningen. Webb-UI:t
(python run_webui.py,
http://127.0.0.1:8765) bygger grafen
visuellt – dra kablar mellan noderna.
Gamla flöden i det nästlade {"steps":[…]}-formatet läses
fortfarande; de migreras automatiskt till grafform vid inläsning och skrivs
om vid nästa sparning.
Motorn är rpa/graph_engine.py – run_graph() börjar
på startnoden och följer kanterna. Efter en vanlig nod följs handtaget
out. if-noder har ett handtag per gren
(case0, case1, … + else);
loop-noder har each (en gång per varv) och
done (efteråt), och kroppens sista nod kopplas tillbaka till
loop-nodens in. rpa/flow_engine.py är kvar som
omslag och kör de enskilda stegen.
Kom igång
python -m venv .venv&pip install -r requirements.txt&python -m playwright install chromiumpython -m rpa.codegen <url>för att hitta exakta selectors mot en riktig, inloggad sida (öppnar en inspector, ingen gissning behövs).python run_webui.pyoch öppnahttp://127.0.0.1:8765för att bygga flödet.- "Kör flöde" sparar och kör flödet i en synlig webbläsare, med live-logg och en variabelpanel.
Fullständiga instruktioner finns i README.md i projektroten.
Stegreferens
by-fältet (var förekommande) styr hur ett element hittas:
text (skiftlägesokänslig delsträng), css
(CSS-selector, stödjer Playwrights utökningar som
:text-is(), :has-text(), :scope) eller
role (ARIA-roll + tillgängligt namn). scope är
page (hela sidan, standard) eller item (bara
inom aktuell loop-post). nth väljer vilken matchning
(0 = första).
CSS-selektorer: flera varianter i samma sträng
En css-selektor kan vara en kommaseparerad lista –
varje del är en egen fullständig selektor, och elementet matchar om
någon del gör det. Praktiskt för att täcka flera filändelser:
a[href$=".png"], a[href$=".jpg"], a[href$=".jpeg"], a[href$=".gif"]
- Skiftläge: attributvärden matchas skiftlägeskänsligt –
.JPGmatchar inte.jpg. Lägg tilli-flaggan (stöds i Chromium):a[href$=".jpg" i]. $=vs*=:$=".png"kräver att värdet slutar på.png– matchar intebild.png?token=…. Använd*=".png"(innehåller) då.- Ofta stabilast: matcha på en ikon-/typklass i stället för
filändelsen, t.ex.
.ids-icon-file-image(alla bildtyper) eller.ids-icon-file-pdf– en selektor, oberoende av skiftläge och query-strängar.
Samma kommalista fungerar överallt där by=css gäller, inklusive
if-villkorens value.
Navigation & väntan
goto Gå till URL
url– adressen att navigera till
wait Vänta (sekunder)
seconds– fast paus
wait_for_load Vänta på sidladdning
Väntar på domcontentloaded. Inga fält.
go_back Gå tillbaka
Webbläsarens "bakåt" (historik). Inga fält. Praktiskt efter att ha klickat in på en post från en lista (t.ex. för att öppna en detaljvy), för att komma tillbaka till listan och fortsätta en loop.
wait_for_login Vänta på inloggning
timeout– sekunder (default 180)
Pollar sidan tills någon text i config.LOGGED_IN_INDICATORS
syns (eller ger upp). Fungerar för BankID, 2FA eller annan manuell
inloggning – verktyget bryr sig bara om att en inloggad-indikator dyker
upp, inte om hur du loggade in.
wait_for_selector Vänta på element
by,value,role?,scope?,nth?timeout– sekunder (default 15)
Sidinteraktion
click Klicka
by,value,role?,scope?,nth?
type Skriv i textfält
by,value,role?,scope?,nth?text– texten som skrivs (stödjer {variabel})
press_key Tryck tangent
key– t.ex.Enter,Tab,Escapevaluetomt → tangenten trycks mot hela sidan. Annarsby/value/role/scope/nthför att trycka på ett specifikt element.
select_option Välj i dropdown
by,value,role?,scope?,nth?option– synlig text på alternativet
check Kryssa checkbox/radio
by,value,role?,scope?,nth?checked–true(kryssa i, default) ellerfalse(kryssa ur)
download Ladda ner
by,value,role?,scope?,nth?
Klickar och sparar den nedladdade filen i data/downloads/.
Misslyckad nedladdning loggas men avbryter inte flödet.
save_attachment Ladda ner bilaga
by,value,role?,scope?,nth?– pekar ut länken (eller ett element som innehåller en<a>). I en loop över bilagerader:by=css,scope=item,value=a[href].filename?– filnamn idata/downloads/(tomt = tas från filens URL; stödjer{variabel}). Krock döps om tillnamn (2).ext.var?– lägger den sparade sökvägen i en listvariabel (så flera bilagor samlas i en lista)timeout?– sekunder (default 15)
Hittar en <a> och: har den en riktig href
(t.ex. PDF-bilagor) hämtas filen direkt via webbläsarens session (behåller
inloggningen, ingen ny flik/skrivardialog). Är det en javascript:-länk
(t.ex. bildbilagor) klickas den i stället – öppnas då en popup med en
nedladdningslänk följer steget den och hämtar filen därifrån (popupens
URL, en fil-/nedladdningslänk i den, eller ett klick som startar nedladdningen).
0 bilagor → list ger antal 0 och loopen kör inga varv. Misslyckad
hämtning loggas men avbryter inte flödet.
Olika hantering för PDF vs. bild: lägg ett if
i loopen med villkoret element_exists, by=css,
scope=item, value .ids-icon-file-pdf
(eller a[href$=".pdf"]) för PDF-grenen och else för
bild. Behövs oftast inte – ett enda save_attachment klarar båda –
men gör det möjligt att t.ex. bara spara PDF:er, eller döpa dem olika.
list value "etj-file-attachment-link", var "bilaga_element"
loop over "bilaga_element":
save_attachment by=css scope=item value="a[href]" var="bilagor"
save_var var "bilagor", filename "bilagor.json"
run_script scripts/merge_and_print.py
--files-from bilagor.json --out data/downloads/klar.pdf --print
capture_pdf Fånga PDF (skriv ut-knapp)
by,value,role?,scope?,nth?– triggern att klicka (t.ex. "SKRIV UT"). Lämnavaluetomt för att fånga sidan som redan visas.filename?– filnamn idata/downloads/(defaultutskrift.pdf, stödjer{variabel})var?– variabel att lägga den sparade sökvägen i (praktiskt för ett efterföljanderun_script-steg)timeout?– sekunder att vänta på ett PDF-nätverkssvar (default 15)
För "Skriv ut"-knappar som öppnar webbläsarens skrivardialog i stället för
att ladda ner en fil. Steget neutraliserar window.print, klickar ev.
triggern och fångar PDF:en i tur och ordning via: (1) ett PDF-nätverkssvar,
(2) en inbäddad PDF i sidan (embed/iframe/object/a
med .pdf), (3) Chrome printToPDF av sidan som den ser ut
(fungerar även i icke-headless läge). Misslyckad fångst loggas men avbryter
inte flödet.
screenshot Ta skärmdump
name?– filnamn utan.png(defaultscreenshot)
Sparas i data/screenshots/.
Variabler & data
set_var Sätt variabel
var,text(stödjer {variabel})
increment Öka variabel
var– variabeln att ökaby?– steg (default1, negativt värde minskar)
Saknad eller icke-numerisk variabel behandlas som 0. Lägg ett
sådant steg sist i en loop så blir {var} 1, 2, 3 …
och kan användas för att särskilja filnamn
(capture_pdf filename stödjer {variabel}).
Behöver du bara varvnumret räcker loopens inbyggda index_var
(default {index}).
clear_var Nollställ variabel
var– variabeln att ta bort
Nästa list_append / save_attachment / extract_row
skapar den på nytt som tom lista. Lägg först i en loop för att
nollställa en samlar-lista per varv (t.ex. bilagor per ärende).
extract_text Läs text till variabel
by,value,role?,scope?,nth?,var
Läser ett elements text till en variabel (skalärt textvärde).
extract_row Extrahera rad (flera kolumner)
var– listvariabel att lägga raden iscope?– normaltitem(körs inuti en loop)fields– lista av{name, by, value, role?}, ett per kolumn
Läser flera namngivna fält (celler) från aktuell post i
ett svep och lägger dem som en rad-post (dict) i
listvariabeln – motsvarar Power Automates "Extract data from table". Ger
strukturerade kolumner istället för en textklump, vilket gör att
save_var skriver riktiga kolumnrubriker i CSV (fältnamnen)
och att en enskild kolumn kan refereras senare med
{item.Kolumnnamn} (se interpolering).
{
"type": "extract_row",
"var": "Tabell_lista",
"scope": "item",
"fields": [
{ "name": "Uppdaterat", "by": "css", "value": "td:nth-child(1)" },
{ "name": "Ärendetyp", "by": "css", "value": "td:nth-child(2)" },
{ "name": "Status", "by": "css", "value": "td:nth-child(6)" }
]
}
list_append Lägg till i lista
var– listvariabel (skapas automatiskt)- Antingen
by/value/role/scope/nth(läser elementets text) ellertext(literalt värde, stödjer {variabel}) omvaluelämnas tomt
Lägger till ett textvärde per anrop – jämför med
extract_row som lägger till en hel namngiven rad i ett
anrop.
save_var Spara variabel (JSON/CSV)
var– variabeln att sparafilename– idata/exports/, inga sökvägar tillåtnaformat?–json/csv, gissas från filändelsen om tomtmode?–overwrite(default) ellerappend
CSV: en lista av dicts (t.ex. från extract_row) ger riktiga
kolumnrubriker från dict-nycklarna. En lista av vanliga textvärden
(t.ex. från list_append med literalt värde) får en enda
kolumn med rubriken value – det är inte en bugg,
CSV kräver en kolumnrubrik och "value" är namnet på den enda kolumnen
när posterna saknar egna fältnamn. Använd extract_row om du
vill ha meningsfulla kolumnnamn istället.
load_var Läs in variabel (JSON/CSV)
var,filename(samma regler somsave_var)
CSV med en enda kolumn "value" läses tillbaka som en lista av textvärden;
CSV med flera kolumner läses tillbaka som en lista av dicts (samma
struktur som extract_row producerar) – round-trip fungerar
alltså sömlöst i båda riktningarna.
run_script Kör Python-script
path– relativ mot projektroten, eller absolutargs?– mellanslagsseparerade argumenttimeout?– sekunder (default 60)var?– sparar scriptets stdout (JSON-tolkat om möjligt, annars text)
Loggar stdout/stderr rad för rad. Flödet stoppas om scriptet avslutar med en felkod.
list Lista poster
value– CSS-selector som matchar flera elementvar– variabeln att spara resultatet i
Sparar {selector, count, preview} i variabeln –
preview är textinnehållet i de tre första träffarna, bara
för att kunna sanity-checka selectorn i variabelpanelen
innan man bygger en hel loop kring den. Loop bryr sig bara
om selector/count.
ocr_read OCR – läs text ur bild/PDF
source–pdf(fil idata/downloads/),window(fönstertitel-regex),region(x/y/w/hskärmkoordinater) ellerimage(fil)var– variabeln att spara texten ipattern?– regex; namngiven grupp(?P<value>…)annars hela träffennear?/near_mode?– returnera värdetsame_line(efter en etikett) ellerbelow(raden under)lang?– OCR-språk, defaultsv-SE
Windows-only (winocr = Windows.Media.Ocr + pymupdf för PDF). Kräver att OCR-språket är installerat i Windows – annars ett fel med exakt DISM-kommandot. En PDF med textlager läses direkt utan OCR.
lookup Slå upp i tabell
from_var– en variabel som håller en JSON-map (frånLäs in variabel); punktnotationcfg.elvis.tabellgår brafile– …eller en JSON-fil idata/exports/key– nyckel att slå upp, stödjer{variabel}(t.ex.{grupp}|{spec})var– resultatet (kan vara ett objekt →{var.fält}funkar sen)ci?– skiftlägesokänsligt (default på);on_missing?–error/empty/ ett defaultvärde
merge_json Skriv nyckel till JSON-fil
file– JSON-fil idata/exports/(skapas om den saknas)key/value–data[key] = value, båda stödjer{variabel}
För kom-ihåg-tabeller: fråga användaren om ett värde med prompt
och spara det här, så finns det nästa körning (läs tillbaka med
Läs in variabel + lookup).
read_url Läs aktuell URL
var– aktuell sidas URLpattern?– regex-utplock, t.ex. ett ärende-id ur adressen
Kontrollflöde
prompt Fråga användaren (paus)
mode–confirm(OK/Avbryt; Avbryt stoppar flödet),input(ett textfält →var),fields(visa de angivna variablerna redigerbara)message– text, stödjer{variabel}fields?– komma-separerade variabelnamn (förmode=fields)
Pausar körningen och visar en ruta på skärmen (egen process). fields
är till för att låta användaren rätta OCR-fel innan värdena
skrivs vidare.
stop Stoppa flödet
message– felmeddelande, stödjer{variabel}
Avbryter körningen (t.ex. när ett ärende inte kan hanteras mekaniskt).
loop Loop (för varje post)
over– variabelnamn att loopa överitem_var?– variabelnamn för aktuellt värde vid loop över en lista (defaultitem)index_var?– variabelnamn för varvräknaren1, 2, 3 …(defaultindex); sätts oavsett looptyp och kan användas som{index}i t.ex. filnamn
Utgångar: each (körs en gång per post, sätter
item/index) och done (efter sista
varvet). Kroppens sista nod måste ha en kant tillbaka till
loop-nodens in – annars körs varv 0 en gång och
done nås aldrig. Se Loop: DOM vs. lista
för de två over-lägena.
if Om / annars om / annars
branches– lista av{condition}, i ordning (första sanna vinner)
Utgångar: case0, case1, … (en per gren) samt
else (ingen gren matchade). Koppla varje grens noder till
respektive utgång. Matchar ingen gren och det saknas en
else-kant tar den vägen slut. Se Villkor.
call_flow Anropa subflöde
target– ett externt sparat flödesnamn, ELLER#<subflow-id>för en lokal subgraf i samma filin– lista av{name, value};name= subflödets indata,valuestödjer{variabel}out– lista av{from, to}; kopierar subflödets slutvariabelfromtill anroparens variabelto
Kör ett annat flöde som ett steg (vanliga handtag in/out).
Subflödet får en egen tom variabel-namnrymd som seedas ur
in (och subflödets deklarerade inputs-default);
bara det du listar i out följer med tillbaka. Samma webbläsare/
flik och inställningar som anroparen. Cirkulära anrop (A→B→A) och för djup
kedja avbryts med FlowError. Se Subflöden & flikar.
Universella fält (alla noder)
enabled–falsehoppar över noden (kryssruta i UI:t); körningen fortsätter viaout.label– valfritt namn på noden (visas i körloggen).on_error–"stop"(default) avbryter körningen om noden misslyckas/får timeout;"continue"loggar felet och går vidare. Väljs i listan bredvid etikettfältet.
jump_to_label finns inte längre – rita en kant
i stället.
Villkor (If)
if-noden utvärderar branches i ordning – första
grenen vars condition är sann följer sin case-utgång
och resten hoppas över. Ingen gren sann → else-utgången följs om
den är kopplad,
annars fortsätter flödet till nästa steg.
| kind | Fält | Betyder |
|---|---|---|
element_exists | by, value, role?, scope?, nth? | Sant om selectorn matchar minst ett element |
element_not_exists | samma som ovan | Sant om selectorn INTE matchar något |
var_equals | var, text | Sant om variabelns textvärde är exakt text |
var_not_equals | var, text | Sant om variabelns textvärde INTE är text |
var_contains | var, text | Sant om text finns som delsträng i variabeln |
:text-is("...") (exakt, skiftlägeskänslig
matchning) är ofta bättre än by=text (skiftlägesokänslig
delsträng) när du vill särskilja t.ex. en cell som är exakt
"Tilldelat" från en som innehåller "Automatiskt tilldelat".
{
"id": "kollaTilldelad",
"type": "if",
"branches": [
{
"condition": {
"kind": "element_not_exists",
"by": "css", "scope": "item",
"value": ":text-is(\"Tilldelat\")"
}
}
]
}
// kant kollaTilldelad --case0--> (noderna som bara ska köras för rader som INTE
// redan är Tilldelat), och deras sista nod --out--> tillbaka till loopens in.
Variabler i text ({variabelnamn})
Följande fält stödjer {variabelnamn}, ersatt med variabelns
textvärde vid körning:
by=text/by=rolesökvärden (i alla steg som har dem)type-stegetstextset_var-stegetstextlist_append-stegets literalatext(närvalueär tomt)capture_pdf-stegetsfilename(undantaget – övriga stegs filnamn interpoleras inte)
Fungerar INTE i CSS-selectors (by=css),
URL:er eller filnamn (utom capture_pdf, se ovan) – där tas
{...} bokstavligt.
Punkt-notation: {variabel.fält} läser ett namngivet fält ur en
dict-variabel (t.ex. en rad från extract_row eller en inläst
flerkolumns-CSV). Okänt variabel- eller fältnamn lämnas oersatt i texten
(bra för att upptäcka stavfel – flödet kraschar inte, men texten blir
synligt fel i loggen).
// item = {"Ärendetyp": "Egenremiss", "Status": "Tilldelat"}
"{item.Ärendetyp}" → "Egenremiss"
"{item}" → '{"Ärendetyp": "Egenremiss", "Status": "Tilldelat"}' (hela dicten som JSON)
"{okänd_variabel}" → "{okänd_variabel}" (oersatt, ingen krasch)
Loop: DOM vs. lista
loop stödjer två helt olika typer av over-variabel:
| DOM-loop (från "Lista poster") | Listloop (vanlig lista) | |
|---|---|---|
| Variabelns form | {selector, count, preview} |
En vanlig JSON-array, t.ex. från list_append eller load_var |
| Vad varje varv ger | Ett riktigt DOM-element (aktuell rad) – scope=item i inre steg söker inom det |
Inget DOM-element; aktuellt värde läggs i variabeln item (eller item_var) |
| Hitta rätt element på sidan | Automatiskt (scope=item) |
Måste sökas upp manuellt, t.ex. med by=text, value="{item.Namn}" |
loop bara hantera "Lista
poster"-resultat – att sätta over till en vanlig listvariabel
gav TypeError: list indices must be integers or slices, not str.
Det är åtgärdat; loop-steget avgör nu automatiskt vilken typ variabeln har.
Klicka på ett element i (eller på) aktuell loop-rad
I en DOM-loop söker scope=item inom aktuell rad. Oftast
vill du klicka ett barn-element – en länk, en cell, en knapp –
inte hela raden (rader har sällan någon klick-hanterare):
list value "table.ids-data-table tbody tr", var "rader"
loop over "rader":
click by=css scope=item value="a" (länken i raden, t.ex. filnamnet)
click by=css scope=item value="td:nth-child(5)" (en viss cell)
Vill du träffa raden/elementet självt (t.ex. spara den i en
lista, eller om hela raden faktiskt är en länk) använd
value=":scope" – CSS-pseudoklassen för "det element sökningen
utgår från":
list_append by=css scope=item value=":scope" var "traffar"
Loggen visar vad som faktiskt träffades, t.ex.
Klickar: css='a' → <a.ids-link href=/case/123 "Bilresa - aktivitetshäfte.pdf">
– jämför det mot vad du menade att klicka.
Recept (vanliga arbetsflöden)
Ladda ner alla bilagor från ett ärende
Bilagorna ligger på ärendets detaljsida. Antalet varierar (0, 1 eller
flera). PDF-bilagor har en riktig länk; bildbilagor öppnar en popup med en
nedladdningslänk – save_attachment hanterar båda.
click (öppna ärendet, t.ex. td:nth-child(5))
wait 1–2 s
clear_var var "bilagor" (nollställ per ärende)
list value "etj-file-attachment-link", var "bilaga_element"
loop over "bilaga_element":
save_attachment by=css scope=item value="a[href]" var="bilagor"
go_back (tillbaka till listan inför nästa varv)
Filerna hamnar i data/downloads/ med sina riktiga namn;
namnkrock döps om till namn (2).ext. bilagor blir
en lista med sökvägarna.
Bara PDF:er, eller olika hantering för PDF vs. bild
loop over "bilaga_element":
if element_exists by=css scope=item value=".ids-icon-file-pdf":
save_attachment by=css scope=item value="a[href]" var="pdf_lista"
else:
save_attachment by=css scope=item value="a[href]" var="bild_lista"
.ids-icon-file-pdf / .ids-icon-file-image är
ikonklasserna i raden. Utelämna else-grenen för att hoppa över
bilder helt.
Slå ihop bilagor till en PDF och skriv ut
Hjälpskriptet scripts/merge_and_print.py (kräver
pypdf + Pillow) tar en ordnad blandning av PDF:er
och bilder: bilder blir centrerade A4-sidor, PDF:er läggs in sida för sida.
save_var var "bilagor", filename "bilagor.json"
run_script path "scripts/merge_and_print.py"
args "--files-from bilagor.json --out data/downloads/arende_{index}.pdf --print"
| Argument | Betydelse |
|---|---|
--files-from <fil> | JSON-array med sökvägar (fil i data/exports/ eller en sökväg) – t.ex. det save_var skrev |
--file <sökväg> | En fil till (upprepa för fler; ordningen bevaras) |
--pdf-latest | Nyaste *.pdf i data/downloads/ först |
--out <sökväg> | Utfil (default data/downloads/merged.pdf) |
--print | Skicka utfilen till skrivare |
--printer "Namn" | Specifik skrivare (default: Windows standardskrivare) |
Skriptet skriver en rad JSON till stdout
({"out": ..., "pages": 3, "printed": true, "skipped": []}) – sätt
run_script-stegets var för att fånga den.
Numrera nedladdade filer i en loop
- Löpande varvnummer räcker: använd
{index}direkt ifilename(loopen sätter det automatiskt). - Tät numrering av bara de faktiskt sparade filerna: lägg ett
increment-steg (var "n") precis före nedladdningen och använd{n}ifilename. Nollställ medclear_varom räknaren ska börja om per ärende.
Göra ett steg "hit or miss"
Sätt stegets on_error till "continue" (listan
bredvid etikettfältet) så loggas ett fel/timeout och nästa steg körs ändå –
bra för ett wait_for_selector eller click som bara
ibland är relevant. På en loop/if gäller det hela
blocket.
Grenar, sammanslagning & loopar
I grafen finns inga hopp – du ritar kanter. Vanliga mönster:
- Gren + sammanslagning: koppla
if-nodenscase-/else-utgångar till varsin nodkedja, och låt varje kedjas sista nod peka på samma efterföljande nod. - Loop:
loop.each→ kroppens första nod; kroppens sista nod →loop.in(loopback);loop.done→ det som ska hända efteråt. - Ett utgångshandtag styr bara en kant (motorn följer den första). Vill du köra flera saker: kedja dem, eller lägg in en nod som samlar ihop.
- Ett skydd stoppar körningen efter väldigt många nodsteg (troligen en
loop utan avslut) –
FlowErroristället för att hänga sig.
Subflöden & flikar
För att hålla stora flöden läsbara går det att bryta ut delar och
anropa dem med en call_flow-nod:
- Lokala subgrafer ligger i samma flödesfil under nyckeln
subflows: [{id, name, nodes, edges, start, inputs}]. I canvasen är de egna flikar bredvid "Main" (+skapar en, dubbelklick döper om).call_flowmedtarget: "#<id>"kör en. - Externa flöden – ett vanligt sparat flöde anropas med
target= dess namn. - Indata/utdata mappas explicit (
in/outpå noden). Subflödet är en "ren funktion": det ser inte anroparens variabler och bara det som listas ioutkommer tillbaka. - Varje subflow-flik har en "Kör denna flik"-knapp som kör
just den subgrafen (med en dialog för dess egna
inputs) – bra för att testa isolerat.
// Main: ... -> call_flow(target="#dubbla", in=[{name:"x", value:"{v}"}],
// out=[{from:"y", to:"r"}]) -> ...
// subflows: [{ id:"dubbla", name:"Dubbla", inputs:[{name:"x"}],
// nodes:[{id:"s1", type:"set_var", var:"y", text:"{x}{x}"}], edges:[] }]
Felsökning
| Verktyg | Vad det gör |
|---|---|
| Variabelpanel (webui) | Klicka på ett variabelnamn efter en körning för att se dess faktiska innehåll (typ + JSON/text) |
Trace (python -m rpa.show_trace) | Öppnar Playwrights Trace Viewer – skärmdumpar, DOM, nätverk per steg, sparas automatiskt varje körning i data/traces/ |
python -m rpa.codegen <url> | Öppnar en inspector mot en riktig, inloggad sida (samma profil) – hovra/klicka för att få exakta selectors, istället för att gissa |
| Håll webbläsaren öppen | Vid "Kör flöde", välj "Håll öppen vid fel"/"Håll alltid öppen" i dropdownen för att kunna inspektera sidan manuellt efteråt |
| Körloggen | Visar varje stegs faktiska (interpolerade) selector/text-värde, inte den oersatta mallen. För click/type/check/select_option/download/save_attachment visas dessutom vilket element som träffades: → <tagg.klass href=… "text"> |
Datamappar
Allt under data/ är gitignorat – kan innehålla
inloggningssession och personlig information.
| Mapp | Innehåll |
|---|---|
data/flows/ | Sparade flöden (JSON) |
data/browser_profile/ | Persistent Chromium-profil (inloggningssession) |
data/downloads/ | Nedladdade filer ("Ladda ner"-steget) |
data/exports/ | JSON/CSV från "Spara variabel"/"Läs in variabel" |
data/screenshots/ | Från "Ta skärmdump" |
data/traces/ | Playwright-traces, en per körning |
data/discover/ | HTML/skärmdumpar från rpa.discover |
Språk (i18n)
Webb-UI:t har engelska som standardspråk med svenska som växlingsbar
översättning (språkväljare i headern, sparas i webbläsarens
localStorage). Bara själva gränssnittet (steg-namn,
fältetiketter, knappar) är översatt – körloggens meddelanden kommer
alltid på svenska direkt från Python-backend, oavsett valt UI-språk.
Inställningar & export
"⚙ Settings" i headern öppnar en dialog med körningsinställningar,
sparade som ett settings-objekt tillsammans med flödets
nodes/edges i samma JSON-fil (data/flows/<namn>.json):
| Nyckel | Standard | Betyder |
|---|---|---|
headless | false | Kör utan synligt fönster. Kräver en redan giltig inloggningssession. |
viewport_width / viewport_height | 1280 / 900 | Webbläsarens fönsterstorlek |
locale | "sv-SE" | Webbläsarens språk/region |
slow_mo | 0 | Millisekunder paus mellan varje Playwright-åtgärd, för felsökning |
notify_on_complete | false | Skrivbordsnotis när körningen är klar |
"Export as script" laddar ner en fristående .py-fil som
kör exakt samma flöde (STEPS + SETTINGS
inbäddade som Python-literaler) genom att importera rpa
och anropa samma run_flow()-motor som webui:t – ingen
logik dupliceras, beteendet blir identiskt. Praktiskt för
schemaläggning (Task Scheduler) av ett flöde byggt i UI:t.
python mitt_flode.py
python mitt_flode.py --headless # tvinga headless oavsett sparad inställning
python mitt_flode.py --close-mode never # håll webbläsaren öppen efteråt
rpa-paketet går att
importera – kör det från projektroten, eller kopiera med hela
rpa/-mappen.Version & git
Projektet är kopplat till en git-remote
(git.kristoffersson.info/repos/RPA-Remisser.git). Push kräver
en personlig token (finns inte sparad i klartext någonstans i repot –
måste anges vid varje push-tillfälle i den här miljön eftersom
credential-cachning inte fungerar i sandboxen).