현상: 특정 작업 완료 후 app을 taskkill.exe로 종료했더니, 해당 위치에서 무한 펜딩. Executor 프로그램은 켜져있고, 오케스트레이터에서도 해당 job을 running으로 인식.

 

조치1(activity의 버그로 추정)

 - start process의 타임아웃을 명시적으로 2000ms로 부여

조치1을 deploy했음에도 여전히 간헐적으로 증상 발생

조치2(taskkill의 연쇄작용으로 추정)

 - taskkill 대신에 kill process activity로 변경

 - 현재까지 이상 없음

현상: AR봇이 특정 시간대에 api로 수행시키는 경우, 중간에 돌다가 로깅을 남기지 않고 봇에서 펜딩되는 현상이 생김. 해당 시간대가 아니면 발생하지 않고, 오케스트레이터에서는 정상 수행중으로 로깅

refer: 이런 케이스가 UR에서 발생하는 경우 job max timeout을 설정하여 trigger하는 케이스를 들었음. 다만 이렇게 체크되는 경우 오랜 시간을 기다려 retry되게 구성할 수밖에 없음. (근본적인 원인 해결은 아님) + AR에서는 job 단위 parameter를 따로 전송하지 못 함.(process level까지만 전달. job 단위 trigger parameter는 오케 -> bot 으로만 내려감)

 

추정 원인

1. 오케스트레이터와의 인증 패킷을 교환하는 과정에서 방화벽 감시 툴이 패킷을 block함

2. ar의 경우 process 단위를 연결해 uirobot을 실행시키더라도 인증 상태의 유효기간(timeout)이 실시간으로 체크되지 않는 경향성이 있어, 중간에 패킷이 block되어 인증이 실패하더라도 오케스트레이터 입장에서는 그냥 잘 돌고 있다고 간주

 

 

디버그 방식

1. nslookup cloud.uipath.com 으로 ip 체크

2. wireshark를 깔고 해당 시간대 레코딩

3. ip.src, ip.dst로 필터링해 결과 체크

 

=> 관련 target 방화벽 해제 후 이슈 없음

 

 

▶ Data Table 중복값 제거 (모든 행이 정확히 같은 케이스일 때)

- dtData = dtData .AsEnumerable().Distinct(System.Data.DataRowComparer.Default)

 

 Data Table 중복값 제거 (Group By 후 첫번째 행 선택)

   중복 시 값 선택: First (특정 건이 선택되도록 유도해야 한다면 sort 선행)

   type 체크 필요(Of String 부분은 맞춰서 변경)

 

- dtData = dtData.AsEnumerable().GroupBy(Function(i) i.Field(Of String)("컬럼명")).Select(Function(g)         g.First).CopyToDataTable()

 

 DataTable의 차집합 , 교집합, 합집합

▷ 차집합
- dtData1 = dtData1.AsEnumerable().Except(dtData2.AsEnumerable(), System.Data.DataRowComparer.Default)

▷ 교집합
- dtData1 = dtData1 .AsEnumerable().Intersect(dtData2.AsEnumerable(), System.Data.DataRowComparer.Default)

▷ 합집합
- dtData1 = dtData1 .AsEnumerable().Union(dtData2.AsEnumerable(), System.Data.DataRowComparer.Default)

 

Datatable내의 값과 비교할 때 타입이 맞지 않아 발생하는 이슈 방지(ex. 1 != "1")

dtOutput = (From p In dtInput.Select Where p(Column_Index).ToString.Equals("StringValue") Select p).ToArray.CopyToDataTable <==== 둘 다 타입을 String으로 맞춰버리기 때문에 엑셀 서식으로 인한 타입 차이 제거

Captcha는 크게 recaptcha와 hCaptcha가 있다.

1. reCaptcha

reCaptcha는 다음과 같이 출력된다

reCaptcha 예시

reCaptcha는 구글에서 만든 API이다.

여러 방식의 우회가 있을 수 있지만, STT(Speech to Text)를 활용하는 게 일반적이다.

 

기본적으로 Captcha는 인간이 분류하기는 쉽고 로봇은 분류하기 어려운 시각 구분 정보를 이용한다.

이 경우 특정 pass를 시각 정보로만 제공하면, 시각 장애인인 사람은 captcha를 통과할 수 없다.

대기업이라면(?) 웹 접근성 가이드에 따라 반드시 다른 수단을 제공해야 한다.

따라서 구글이 만든 reCaptcha는 거의 항상 Speech 문제로 변경 가능하다.

(거의 항상이라고 쓴 이유는 STT를 단위 시간에 너무 많이 호출하는 경우 '너 로봇인 거 같애'라는 문구를 출력하면서 변환 안 시켜주기 때문)

STT는 이전부터 상당히 기술이 많이 좋아져서 웬만해서는 사람 수준으로 인식 가능하다.

RPA에서는 STT를 이용한 extension을 이용하는 게 좋은데, 대표적인 게 Buster: Captcha solver for human 이다.

https://chromewebstore.google.com/detail/buster-captcha-solver-for/mpbjkejclgfgadiemmefgebjfooflfhl

 

Buster: Captcha Solver for Humans

Save time by asking Buster to solve CAPTCHAs for you.

chromewebstore.google.com

보통 selector는 제대로 잡기 어려워서 image click으로 잡기 십상인데

이미지 인식을 정확히 하기 위해 extension 고정핀으로 image를 노출시키지 않는 것을 추천한다.

고정핀 활성화가 되지 않은 모습
아래 buster의 이미지를 클릭하면 STT로 전환되며 자동으로 Captcha가 풀리게 된다.

 

2. hCaptcha

hCaptcha 예시

hCaptcha는 구글 reCaptcha가 접속정보를 추적하는 거 같다는 비판이 일어 만들어진 캡차라고 한다.

hCaptcha는 많은 봇들이 STT로 우회하는 것을 알고 있어서 STT 옵션을 주지 않는다.

사악한 샘플 ㅠ 인간인 나도 답을 모르겠다

이 경우는 2가지 방법이 있는데 하나는 cookie를 세팅하는 모듈을 만드는 것이다.

묘하게 불친절해 보이는 번역이라 어울린다

자동화 하는 로컬에 hCaptcha 쿠키를 설정방식인데, 쿠키를 삭제하지 않는다면 24시간 지속된다.

다른 하나는 역시나 extension에 의존하는 것이다.

https://chromewebstore.google.com/detail/captcha-%ED%95%B4%EA%B2%B0%EC%82%AC-%EC%9E%90%EB%8F%99-hcaptcha-r/hlifkpholllijblknnmbfagnkjneagid

 

CAPTCHA 해결사: 자동 hCAPTCHA reCAPTCHA 자유롭게

모든 페이지에서 AI를 사용하여 hCAPTCHA 및 reCAPTCHA를 해결하세요. 더 쉬운 데이터 수집을 위해 NoCoding Data Scraper와의 원활한 통합

chromewebstore.google.com

"Captcha 해결사" 라는 extension인데 켜놓으면 알아서 captcha를 풀어준다. (hCaptcha든 reCaptcha든 다 풀어줌)

다만 이 extension은 단점이 두 가지 있다.

1) reCaptcha가 이 extension이 있으면 아예 Captcha를 안 보여주는 경우가 있다. (recaptcha 사이트에 접근하는 봇은 영향도가 있음)

2) 문제가 어렵다 보니 아예 못 풀 수도 있다. (인내심을 가지고 기다리면 많이 틀리다가 어찌저찌 넘어가는 간다 ㅠ)

 

3. 결론

hCaptcha가 나왔을 때 특별히 recaptcha랑 안 겹치고 daily 과제라면 extension을 쓸 수 있다.

하지만 과제 안정성을 위해서는 쿠키를 세팅하도록 하자.

reCaptcha는 꼭 buster가 아니라도 STT를 안 해줄 수 없기 때문에,

상대적으로 뚫기가 쉬우니 웬만하면 과제 진행을 해도 무방하다.

단 reCaptcha도 횟수가 많으면 컷당하니 로그인 시도가 잦으면 안 된다.

 

 

증상: UIFramework default로 잡으면 최초 인식 실패함. 수동으로 default를 설정 후 잡으면 통으로 잡히고 프레임워크를 한번 새로고침 해줘야 인식 가능. 이미지로 클릭 또는 attach window 같은 걸 선행해도 마찬가지 증상이 발생.

조치: UIFramework UIA로 Exist를 앞쪽에 추가

 

신기한 케이스인 거 같다. 아마 app에 붙을 때 UIA 방식은 허용되고, default는 허용 안 되는 것으로 보인다.

일단 UIA로 앱에 한번 붙기만 하면 default로 잡아놨던 셀렉터들도 잘 작동하고 있다.

현재 페이지 URL을 가져오려고 하면 browser 객체에서 가져와야 될 느낌인데

굳이 그러지 않고 page의 아무 element나 잡고

get attributes 에서 url을 적고 output을 받으면 된다.

※ 자동으로 설정되는 리스트에는 없는데 가져온다.

<?xml version="1.0" encoding="utf-16"?><ClipboardData Version="1.0" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:p="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:sap2010="http://schemas.microsoft.com/netfx/2010/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:ui="http://schemas.uipath.com/workflow/activities" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><ClipboardData.Data><scg:List x:TypeArguments="x:Object" Capacity="1"><ui:InvokeCode ContinueOnError="{x:Null}" x:Name="__ReferenceID0" sap2010:Annotation.AnnotationText="iCollectCnt만큼 뽑아줌" Code="Dim randomGenerator As New Random()&#xA;RandomThreeList = OriginalList.OrderBy(Function(x) randomGenerator.Next()).Take(RequestNo).ToArray()" DisplayName="랜덤으로 뽑기 Invoke code" VirtualizedContainerService.HintSize="1436,196"><ui:InvokeCode.Arguments><p:InArgument x:TypeArguments="x:Int32" x:Key="RequestNo">[iCollectCnt]</p:InArgument><p:InOutArgument x:TypeArguments="s:String[]" x:Key="RandomThreeList">[arrRandomCard]</p:InOutArgument><p:InArgument x:TypeArguments="s:String[]" x:Key="OriginalList">[arrNormalCard]</p:InArgument></ui:InvokeCode.Arguments><WorkflowViewStateService.ViewState><scg:Dictionary x:TypeArguments="x:String, x:Object"><x:Boolean x:Key="IsPinned">True</x:Boolean><x:Boolean x:Key="IsAnnotationDocked">True</x:Boolean></scg:Dictionary></WorkflowViewStateService.ViewState></ui:InvokeCode></scg:List></ClipboardData.Data><ClipboardData.Metadata><scg:List x:TypeArguments="x:Object" Capacity="4"><scg:List x:TypeArguments="x:Object" Capacity="4"><x:Reference>__ReferenceID0</x:Reference></scg:List></scg:List></ClipboardData.Metadata></ClipboardData>

 

 

 

그냥 숫자 하나를 Random으로 뽑으려면,

New Random().Next(min, max)

2022년 10월인가부터 MS에서 보안상의 이유로 일반 smtp 호스트 + 포트만 가지고 메일을 보낼 수 없게 했다.

그에 따라 방식이 좀 바뀌었다.

Secured SMTP (required info)

Server: "회사도메인.mail.protection.outlook.com"
Port: 25
Ignore CRL: True
SecureConnection: StartTls
Sender Address: "보내는 사람으로 할 메일"

 

결국은 host가 나름 protection 서버로 넘어간다는 게 다른 점이 되겠다.

원래라면 tls나 ssl을 검사하겠으나 ignore CRL을 통해 skip해 주었다.

 

※ 쓰고보니 수신자가 좀 길어질 때는 에러가 난다. 이에 대비가 필요하다.

+ Recent posts