독자가 기본적으로 오토핫키의 이해하고 사용한다는 가정하에 작성했습니다. 아래는 따로 설명하지 않습니다.
- ㅡ If 조건식
- ㅡ 익스프레션 변수에 대한 이해
- ㅡ IfInString, MsgBox 명령어
- ㅡ 함수에 대한 이해
파싱이란, 특정 변수에서 문자열을 추출해는것을 의미하는데요.
배포하는 프로그램에서 실시간 공지사항이나, 최신버전의 업데이트알림이 필요할떄가 있습니다. 이런 경우에 웹상의 정보를 파싱하면 되겠죠
파싱을 하기위해서는 먼저, 웹의 데이터를 받아와야하는데 일반적인 방법으로는
UrlDownloadToFile 함수로 웹페이지를 다운받거나, WinHttp로 웹페이지 텍스트를 변수로 저장하는데요
혹은 윈도우 API함수를 사용해 웹페이지를 메모리로 읽어올수도 있습니다.
여기에서는 윈도우 API를 사용하여 웹페이지를 메모리로 읽는 방법을 알아보도록 하겠습니다.
가장 빠르고, UrlDownToFile처럼 파일이 남지도 않습니다.
사실 파싱을 위한 가장 강력한 방법은 ActiveX로 HTML파일을 각 파트별로 읽어오는 방식입니다
파싱명령어나 정규식을 쓸 필요없이 페이지 정보를 가져오는 것이 가능하죠.
하지만 이번 글에서는 문자열을 추출하기위한 파싱에 대해서만 적고, ActiveX 파싱은 나중에 따로 작성하도록 하겠습니다.
필요 라이브러리
ReadURL(URL, encoding = "utf-8") {
static a := "AutoHotkey/" A_AhkVersion
if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
return 0
c := s := 0, o := ""
if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
{
while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s > 0)
{
VarSetCapacity(b, s, 0)
DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
o .= StrGet(&b, r >> (encoding = "utf-16" || encoding = "cp1200"), encoding)
}
DllCall("wininet\InternetCloseHandle", "ptr", f)
}
DllCall("wininet\InternetCloseHandle", "ptr", h)
return o
알고리즘
1. 프로그램을 실행하면, 웹 주소로 접속해 페이지정보(블로그 글, 개인 호스팅 등)을 읽어온다
2. 정보를 비교/분석후 다음으로 진행
아래 예제 코드에서 사용하는 주소는 저의 GitHub 주소를 사용합니다. 여기를 클릭해 웹페이지 정보를 확인해보세요
웹페이지에는 '안녕하세요' 라는 문자열이 있네요
#include ReadURL.ahk ; 라이브러리 파일을 불러온다, /Lib 폴더에 라이브러리를 저장했다면 생략가능
URL := "https://raw.githubusercontent.com/Visionary1/-/master/README.md" ; URL라는 변수에 웹 주소 저장
Result := ReadURL(URL) ; Result 라는 변수에 웹 주소를 읽어온 결과값을 저장 (안녕하세요 가 저장되겠네요)
MsgBox % Result ; Result 변수 결과 출력
적용
*위 예제에서 사용한것처럼 주소를 GitHub의 Raw페이지를 이용한다면 HTML의 정보에는 텍스트뿐이라서 파싱이 정말로 쉬운데
개인블로그(네이버,티스토리 등) 등의 개인홈페이지를 사용한다면, HTML에는 많은 정보가 들어 있어 원하는 부분만 따로 잘라내야합니다. 따라서, 깃허브를 사용하실줄 안다면 사용하시는걸 적극 추천합니다.
이제 페이지정보를 읽어오는것은 문제가 없군요,
이제 웹페이지 정보를 나눠서 원하는 값만 추출하는, 파싱을 배워보도록 하겠습니다.
오토핫키에는 String 관련 명령어가있지만 웹페이지(HTML)에서 문자열 추출에는 적절하지 않습니다.
간결한 코드로 파싱이 가능한 정규식 RegExMatch 에 비해서 너무나 긴 코드를 요구하기 때문이죠.
단순히 서버온,오프 체크만 한다면야 단순히 IfinString 만으로도 체크가 가능하지만,
버전체크, 구버전일시 자동으로 새버전 다운로드주소로 이동하는 등의 작업을 하고싶다면 정규식을 사용해야 합니다.
파싱을 위한 정규식, RegExMatch 의 구문은 아래와 같습니다.
RegExMatch(읽어올변수,"제거할 앞 문자열(.*?)제거할 뒷 문자열",추출값변수)
주의하실점은 추출값을 표현할때는 추출값변수에 1을 붙여야합니다.
아래의 예를 확인하세요.
읽어올변수 :="제거할 앞 문자열/이 부분이 추출됨/제거할 뒷 문자열"
RegExMatch(읽어올변수,"제거할 앞 문자열(.*?)제거할 뒷 문자열",추출값변수)
MsgBox % 추출값변수1
결과는 예상가능하듯 아래 사진과 같습니다.
이제 더 나아가 웹페이지를 메모리로 읽은다음 정보를 파싱해볼까요?
예를 위해 제 블로그 글을 파싱해보겠습니다. http://knowledgeisfree.tistory.com/1
시각적으로 보이는 페이지는 위 사진과 같은데, HTML은 아래 사진과 같이 복잡합니다.
이와 같은 페이지에서 ProgramVersion에서 2.6 을
Announce 에서 "이제 네이버에서 제 블로그 검색이되요!" 등을 어떻게 파싱하는지 아래 예제를 확인하세요.
URL := "http://knowledgeisfree.tistory.com/1"
Version := 2.5
Address := ReadURL(URL)
IfInString, Address, Server/is/Online ;서버가 Online 상태인지 확인한다
{
RegExMatch(Address,"@ProgramVersion/(.*?)@",Latest)
RegExMatch(Address,"@Announce/(.*?)@",Notice)
if (Latest1 > Version)
MsgBox, 4164, , % "최신버전 " Latest1 "이 존재합니다`n다운받으시겠어요?"
IfMsgBox, Yes
{
RegExMatch(Address,"@Update/(.*?)@",Patch)
Run, %Patch1%
}
MsgBox, % Notice1
}
'프로그래밍 > AHK 메뉴얼' 카테고리의 다른 글
[팁] 코드의 속도, 성능을 높이는 한줄 팁 모음 (8) | 2015.10.09 |
---|---|
[라이브러리] Easyini - 네이티브 ini (15) | 2015.09.24 |
[공개] 오토핫키 반응형 학습 어플리케이션 (33) | 2015.02.22 |
[정보] 오토핫키 간이 에디터 (2) | 2015.02.18 |
[메뉴얼] GUI창 스킨입히기 (19) | 2015.02.15 |