Chuyển tới nội dung chính

Copy từ phần mềm này, nhập sang phần mềm kia

Công việc lâu đời nhất chưa ai tự động hóa trong mọi văn phòng: danh sách nằm ở một phần mềm, form nằm ở phần mềm khác, và một người ngồi gõ lại. Không phần mềm nào có đường xuất mà bên kia nhập được, nên kênh duy nhất giữa chúng chính là kênh một con người vẫn dùng — màn hình, bàn phím, và clipboard.

Trang này dựng đúng flow đó từ đầu tới cuối. Đây là flow thật, 30 node, chạy tới Success.

Mục tiêu

Đọc năm bản ghi khách hàng từ một file văn bản và nhập từng bản ghi vào một form web chạy trong Chrome, với một captcha chắn ngay ở cửa vào.

Nó minh họa:

  • Hai cửa sổ giữ cùng lúc, mỗi cửa sổ được gọi bằng alias chứ không phải bằng "cái đang ở trước mặt"
  • Một cú Ctrl+C mang cả file về thành một biến flow
  • split() biến chuỗi đó thành năm bản ghi, mỗi bản ghi năm trường
  • Một vòng thử có cận quanh captcha — ba lượt rồi thôi, không bao giờ lặp vô hạn
  • Click đúng chỗ Find Image vừa tìm thấy, thay vì một điểm cố định

Điều kiện: đã bật Desktop Mode, và một flow có target là desktop.

Hình dáng của nó

Ba biến, đều phạm vi flow:

BiếnKiểuMặc địnhChứa
vars.noidungstring""Cả file dữ liệu, đúng như đã copy
vars.inumber0Đang ở bản ghi thứ mấy
vars.jnumber0Đang ở lượt captcha thứ mấy

Bước 1 — Mở cả hai phần mềm, và đặt tên cho chúng

Hai node Open App. Điều quan trọng không phải là chúng khởi chạy được cái gì đó; mà là mỗi node chiếm một cửa sổ dưới một cái tên mà cả flow còn lại dùng được.

FormFile dữ liệu
Chương trìnhchrome.exenotepad.exe
Tham số--app=http://…/form.html, --window-size=1000,760, --window-position=880,60, một --user-data-dir riêng…\khach_hang.txt
Execution ContextSpecific WindowSpecific Window
Tiêu đề chứaQLBHkhach_hang
Aliasqlbhnguon
Wait after1200 ms1200 ms

Hãy bấm Browse… để chọn chương trình thay vì gõ đường dẫn. Nó nhận .exe, nhận .bat, và — rất tiện — nhận cả .lnk, nên cái shortcut trình duyệt sẵn trên Desktop là một câu trả lời hợp lệ.

Cho Chrome một profile riêng

--user-data-dir trỏ vào chỗ riêng chính là thứ khiến việc này lặp lại được. Không có nó, Chrome giao URL cho bất kỳ cửa sổ nào bạn đang mở sẵn, và flow thừa hưởng luôn tab của bạn, phiên đăng nhập của bạn, các popup thông báo của bạn. Có nó, flow luôn nhận một cửa sổ sạch, còn việc lướt web của bạn không bị đụng tới.

Các alias là toàn bộ ý đồ thiết kế. Mọi node phía sau đều nêu qlbh hay nguon trong Execution Context của chính nó, nên "gõ cái này" và "copy cái kia" rơi đúng phần mềm bất kể trong lúc flow chạy người dùng có click vào đâu. Không node nào trong flow này tác động lên "cửa sổ đang hoạt động".

Bước 2 — Qua captcha, theo cách có cận

Một node Captcha ở chế độ solveAndApply, giới hạn vào một vùng của cửa sổ qlbh, vượt qua cửa thứ nhất. Cửa thứ hai — mã xác minh — được bọc trong một vòng lặp không thể chạy mãi:

Loop "ma", chế độ Count, tối đa 3, biến đếm vars.j
Captcha: đọc mã và gõ vào (timeout 60s / 20s)
Find Image: danh sách sản phẩm hiện chưa?
Success → Break
Failure → Loop End (thử lại)
Loop End

Chính Find Image mới là phần xác minh. Node captcha thành công nghĩa là nó đã gõ một cái gì đó, không phải là trang đã chấp nhận — nên flow đi tìm một thứ chỉ tồn tại ở bên kia cửa, rồi mới thoát vòng.

Ba lượt, rồi vòng lặp tự kết thúc. Thử lại mà không có cận là cách phổ biến nhất khiến một flow không người trông trở thành một flow treo.

Bước 3 — Lấy cả file bằng một cú copy

Đây là mẹo đáng học. Ba node, tất cả đều scope vào nguon:

NodeThiết lậpVì sao
ClickMột vùng phủ lên ô văn bản, waitAfterMs 400Focus. Cửa sổ nổi lên trước không có nghĩa là ô văn bản của nó đang nhận phím
Key PressCtrl + AChọn hết
Key PressCtrl + C, Lấy vào biến noidung, timeout 3000 msChữ vừa copy rơi vào một biến flow

Ô Lấy vào biến biến một tổ hợp copy thành một phép đọc. Sau node này, vars.noidung giữ đúng nội dung file — nguyên dấu — và không có OCR nào tham gia, nên không có gì để đọc nhầm.

Cú click trước khi copy không phải tùy chọn

Nếu không copy được, node rẽ Failure chứ không trả về thứ đang sẵn trên clipboard. Đó là chủ đích: nhìn vào nội dung thì hai thứ đó y hệt nhau, và một flow âm thầm gõ bản copy tuần trước vào form là cái sai không ai phát hiện. Nguyên nhân thường gặp là focus — nên mới có cú Click.

Bước 4 — Đi qua các bản ghi bằng split()

File dữ liệu mỗi dòng một trường, mỗi bản ghi năm trường:

KH001
Nguyễn Văn A
0901234567
12 Lê Lợi, Q1
1500000
KH002

Một vòng lặp qua năm bản ghi, và mỗi trường là một chỉ số trong kết quả split:

Loop "don", chế độ Count, tối đa 5, biến đếm vars.i

Input Text split(vars.noidung, "\n")[vars.i * 5 + 0] → Mã KH
Key Press Tab
Input Text split(vars.noidung, "\n")[vars.i * 5 + 1] → Tên KH
Key Press Tab
Input Text split(vars.noidung, "\n")[vars.i * 5 + 2] → Điện thoại
Key Press Tab
Input Text split(vars.noidung, "\n")[vars.i * 5 + 3] → Địa chỉ
Key Press Tab
Input Text split(vars.noidung, "\n")[vars.i * 5 + 4] → Số tiền
Key Press Tab
Key Press Enter → lưu

Loop End

vars.i * 5 + n chính là toàn bộ cách đánh chỉ số: biến đếm vòng lặp chọn bản ghi, hằng số chọn trường. Đổi file sang sáu trường một bản ghi thì chỉ một con số đổi ở năm chỗ.

Tab chuyển giữa các ô vì đó là điều một người vẫn làm — nó không cần tọa độ nào, và nó sống sót qua việc form bị dời hay đổi kích thước.

Bước 5 — Click đúng chỗ vừa tìm thấy ảnh

Bên trong vòng lặp, trước khi gõ, một Find Image định vị dòng sản phẩm trên qlbh, và node Click ngay sau đó không dùng điểm cố định. Mục tiêu của nó là một kết quả Find Image sống — đúng tọa độ lần tìm vừa rồi tạo ra.

Điều này quan trọng vì danh sách có cuộn. Một tọa độ cố định đúng cho tới khi trang xê dịch; một tọa độ đến từ chính lần tìm vừa chạy thì luôn đúng, và nếu lần tìm hỏng thì cú click không xảy ra chút nào.

Kết quả

Flow kết ở một node Stop với trạng thái success, và Desktop Dashboard hiện nó trong hàng đợi với chữ Success màu xanh.

Desktop Dashboard sau lần chạy

Một máy, mỗi lúc một flow, và một lần chạy đã xong nằm trong hàng đợi.

Vì sao dựng theo cách này

Quyết địnhPhương án kia, và vì sao không
Giữ cửa sổ bằng alias"Cửa sổ đang hoạt động" — người dùng lỡ click một cái là flow gõ vào email của họ
Clipboard, không phải OCROCR đọc nhầm được; copy thì không. Dùng OCR khi không có chữ để copy, không phải khi có
Một cú copy, rồi split()Năm mươi cặp Shift+End/Ctrl+C — năm mươi cơ hội mất focus
Vòng captcha giới hạn 3Thử lại không cận là cách một flow biến thành tiến trình treo
Find Image xác minh, captcha chỉ hành độngNode captcha gõ được không có nghĩa trang đã nhận
Click từ kết quả Find ImageĐiểm cố định đúng cho tới khi danh sách cuộn
Tab giữa các ôNăm tọa độ sẽ hỏng khi cửa sổ đổi kích thước

Mẹo

  • Test Node trước Test Flow. Từng node kiểm tra riêng được, và khi đó nó tự bind Execution Context của chính nó — nên bạn xác nhận được cú Ctrl+C có thật sự đổ đầy noidung mà không phải ngồi chờ hết captcha.
  • Để ý các giá trị waitAfterMs. Chúng nhỏ (105–700 ms) và chúng gánh việc: một form vẽ lại sau Tab cần khoảng nghỉ đó hơn là cần phím gõ nhanh.
  • Đặt cận vòng lặp mà bạn bảo vệ được. tối đa 5 ở đây là số bản ghi; nếu file có thể dài hơn, hãy đọc ra số lượng thay vì đoán cho cao.
  • Giữ hình dạng file dữ liệu ở một chỗ. Con * 5 xuất hiện trong năm biểu thức. Nếu nó còn lớn hơn nữa, một node Variable giữ số trường là đáng thêm.

Ghi chú và giới hạn

  • Một desktop, mỗi lúc một flow. Các lần chạy desktop là tuần tự — workspace này không có đội instance, nên flow thứ hai phải chờ.
  • Clipboard là của cả máy. Một flow khác copy đúng lúc đó thì không phân biệt được với flow này. Chỉ nên có một cú copy đang trong không trung.
  • Cửa sổ Chrome --app= không phải lúc nào cũng mô tả duy nhất được. Nó sinh ra một cửa sổ song sinh vô hình dùng chung cả tiêu đề lẫn class. Nếu trình chọn cửa sổ từ chối chọn, hãy dùng một cửa sổ Chrome thường — cái đó mô tả được.
  • split() không tự trim. Một dòng trống ở cuối file dữ liệu sẽ thành một bản ghi rỗng. Hãy trim() bản copy trước, hoặc bảo đảm file không có ký tự xuống dòng ở cuối.

Trang liên quan