2018. 5. 11. 12:23

>>재미로 구현해본 내용이며, 현재 동작하지 않습니다<<

 

우리는 그 성취감에 도취되어 있을뿐 악의적인 목적은 없다!

 

0x01. 올파일포유서비스 소개

인터넷상의 유료웹하드 파일이즈(http://fileis.com) 사이트를 미러링 하여, 모바일 / PC상에서 공짜로 원하는 영화, 드라마, TV, 유틸 등의 파일을 마음껏 다운로드 할 수 있도록 도와주는 서비스

 

0x01-1. 720HD로 크게 보셔도 제대로 안보여요 하지만 나름 소리도 나와요!!

  - 자세히 보아야 보인다. 오래보아야 이해된다. 너도 그렇다. ㅡㅡ;;

 

0x02. 서비스 사용법

  0x02-1. 텔레그램 찾기에 "helloongfile" 검색

  0x02-2. start 버튼 클릭 또는 "/시작" 명령으로 인증요청

  0x02-3. 관리자 인증 승인 후 "/도움말" 명령어 사용 후 시작

 

0x03. 핵심기능

  0x03-1. 파일이즈 핵심 기능 봇 래핑

    - 사용자 인증, 관리, 파일 다운로드, 다운로드 완료 알림

  0x03-2. 전용브라우저 제작

    - 로컬 프록시 서버 구성 후 파일이즈 사이트로의 요청/응답 내용을 수정 서버내 포터블 다운로드 모듈 및 텔레그램 봇과 연동, 다운로드 할 수 있도록 기능 구현

 

0x04. 장점

  0x04-1. 경제성!! 사용자는 공짜!! 운영자만 유료라는 백년에 한번 나올까말까한 사상 초유의 마진구조 운영자의 다퍼주고 깔끔하게 떠나겠다!!라는 마인드가 십분 반영된 서비스 사용자는 운영자가 결제한 사이트를 미러링 받으므로 공짜!!

  0x04-2. 접근성!! 모바일로도 언제 어디서나 검색 / 다운로드 / 시청 가능(단, 데이터 무제한 요금제 또는 WIFI 사용시만)

  0x04-3. 보안성!! 웹하드 / 토렌트 시드공유 사이트등에서 유포되는 악성코드 또는 그리드웨어 설치 위험 감소

    - 실제 파일이즈 다운로드 전용프로그램 설치시 사용자 몰래 시스템 백그라운드에 숭악한 그리드웨어 설치

 

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑사용자는 요기까지만↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

 

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓개발과정 및 소스가 필요하신 분들은 요리로↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

0x05. 잡담

  0x05-1. 올파일포유 동작구조 삼줄 요약

- 텔레그램 메신져 동작 

  요청: 텔레그램 메신져 ===> 올파일포유 메신져 데몬 ===> 진짜파일이즈 웹하드

  응답: 진짜파일이즈웹하드 ===> 올파일포유 메신져 데몬 ===> 텔레그램 메신져

 

- 전용브라우저

  요청: 전용브라우저 ===> 올파일포유 웹서버 데몬 ===>진짜파일이즈 웹하드

  응답: 진짜파일이즈 웹하드 ===> 올파일포유 웹서버 데몬 ===> 전용브라우저

 

  0x05-2. 분석과정

1. 크롬 개발자 도구[F12]를 사용하여 고속다운로드버튼 Onclick() 이벤트 확인

그림1

 

2. do_down_confirm ==> down_confirm_layer.php 로 리다이렉팅

그림2

 

3. Fiddler[https://www.telerik.com/fiddler]로 http 통신 디버깅

  - 서버단의 down_confirm_layer.php에서 파라메터인 파일아이디, 사용자아이디 결제방법을 이용하여 실결제가 이루어지고, 이후 익스플로러인지 기타 브라우저인지 체크하는 로직들이 포함된 do_down()으로 분기

그림3

 

4. do_down javascript function()에서 check_and_downoad() 호출[호출시 down_init.php 파라메터 포함]

그림4

 

5. 서버단의 down_init.php에서 down_confirm_layer.php 결제후 생성된 구매아이디를 사용자 정보와 함께 응답값으로 생성해 실제 다운로드런처를 실행하는 nfile_download()로 분기

그림5

 

6. 이후 SLB() 함수등을 거쳐 네비게이팅중인 브라우저가 익스플로러인지, 기타 브라우저인지 판단 후 기타브라우저 일 경우 down_multbrowser.php로 분기하여 기타 브라우저에서 웹하드 다운로드 런처를 실행하기 위한 꼼수인 로컬 웹서버를 호출할 페이지를 제작 후 강제 전송함.

이때 생성되는 페이지는 아래와 같으며, 이 페이지는 보이는 대로 127.0.0.1(로컬호스트)의 9696포트로 전송되어짐.

그림6

이 요청을 처리하는 웹서버는 FileisLocal.exe이며, 파일이즈 웹페이지상의 다운로드 모듈 설치시 설치되어지는 실행파일 중 하나임. 해당 실행파일은 FileisService.exe라는 실행파일로 윈도우 서비스 페이지에 등록되어지며, OS기동시 해당 서비스에 의해 런칭되어져 항시 상주하게 됌

FileIsLocal.exe가 해주는 역할은 FileIsWebCtrl.dll이 하는 역할과 동일하며, 업로드 런처, 다운로드 런처 등이 프로세스상에 존재하는지 확인 후 없다면 해당 런처들을 기동 후 핸들을 획득하여 동작에 맞는 메세지를 전송하여 사용자의 입력을 파일이즈 런처에 인터페이스 하는 역할을 수행한다. FileIsLocal.exe는 익스플로러 이외의 브라우저에서 위 역할들을 수행하며, FileIsWebCtrl.dll은 익스플로러 브라우저내에서 위 역할들을 수행한다.

 

FileIsWebCtrl.dll은 익스플로러로 해당 웹사이트 서핑시 아래와 같은 자바 스크립트에 의해 구동되며 해당 라이브러리의 동작은 FileIsLocal과 동일하다. 해당 dll은 일반적인 ActiveX와 동일하게 레지스트리상에서 클래스 ID로 검색이 가능하며 아래와 같은 경로에 존재하는 것을 알 수 있다.

그림7

 

그림8

 

그림9

 

그림10

 

 

그럼 다운로드 런처가 기동되는 방법을 알았으니 해당 런처를 분석하여 이후 어떤 과정으로 다운로드가 이루어 지는지 확인 해보자.

 

먼저 그림7~10에 걸쳐 브라우저별로 실제 다운로드를 실행할 모듈 2개중 어느 모듈을 분석할지 결정을 해야 하는데 결론적으로 보면 어느 모듈을 보든 마찬가지지만 좀더 간편하게 진입점을 찾을 수 있는(사실 너무 간단한 분석이라 동일하지만) ActiveX로 결정을 하고 진행을 하였다. 위의 그림 10에서 찾은 ProgID를 바탕으로 python의 win32com 모듈을 사용하여 간단하게 해당 ActiveX모듈을 메모리에 올린 후 그림7과 동일한 WebCtrl 컨르롤로 선언하여 동일한 파라메터사용 DownLoad() 모듈을 호출하면서 해당 python 프로세스에 x64Dbg를 attach한 후 dll 엔트리포인트 진입시부터 디버깅을 하면 되겠다 추정하며 작업을 시작하였다.

 

python으로 com객체를 연결시키는 작업은 모듈선언을 제외하고는 1줄이면 된다. 쉽다 편하다 눈물이 난다.

import win32com

WEBCTRL = win32com.client.Dispatch("WebControl.WebBBS.1")

이게 다다. ㅡㅡ;; 그럼 호출하는 방법은??

WEBCTRL.DownLoad(user_id, user_pw, 0, file_id, purchase_id, ftp_type, 1)

이게 다다. ㅡㅡ;; 대다나다... 조타 귀도행님에게 감사드린다.

 

각설하고 위 첫번째 코드를 x64dbg를 부착시켜놓은 파이썬 인터프리터에 입력 후 엔터키를 입력하면

해당 dll이 로드되는 것을 볼 수 있으며, dll의 참조 라이브러리에 브레이크 포인트를 걸거나 또는 글로벌 옵션에서

모든 dll 엔트리포인트에서 브레이크 포인트를 발생 시킬 수 있으며 개인취향에 따라 작업하면 된다.

 

위의 작업을 진행후 2번째 줄을 입력하여 트레이싱 하다보면, 금새 아래와 같은 디스어셈블링 코드를 볼 수 있게된다.

그림 11.

 

그림11과 같이 webctrl에서는 Fileis_class_down 이라는 클래스명으로 FindWindowA() Win32Api를 호출 프로세스 리스트상에 FileisDown.exe가 실행중인지를 체크 후 실행중이 아니면 다운로드모듈을 실행하고 실행된 윈도우의 핸들을 반환받고, 이미 실행중이면, 해당 윈도우 핸들에 다운로드 파일에 대한 파일아이디와 구매아이디를 0#<파일아이디#<구매번호#<R 과 같은 문자열로 구성하여 SendMessageA로 전송하고 FileisDown.exe 프로세스에서는 런처에서 보내져온 SendMessage를 디스패치하여 파싱 후 FileisCMC.dll의 다운로드파일정보 추출 및 구매이력 확인등의 로직을 거쳐 NAT.dll 모듈로 실제 다운로드 서버에 접속 후 다운로드를 시도하게 된다. 아래에 앞의 과정들이 진행되는 과정의 스냅샷을 첨부한다.

그림12. FileIsDown.exe가 실행중이지 않을경우 ShellExecuteA() API로 실행하는 부분

그림12에서 FileIsDown.exe가 실행시 실행 파라메터 3개를 가져가며, 아이디, 해쉬패스워드, 알수없는값1 로 실행 됨을 확인하였다. 이를 command prompt상에 입력하면 정상적으로 fileisdown.exe가 실행되는 모습을 볼 수 있다.

 

그림13. 실행되어진 fileisdown.exe의 클래스명이 Fileis_class_down 임을 spy++로 확인

 

그림14. fileiswebctrl.dll에서 fileisdown.exe윈도우로 다운로드할 파일번호와 구매번호를 메세지로 전달

 

그림15. 그림14에서 메세지 전달과 동시에 백그라운드의 다운로드모듈에 해당 파일이 추가되어지는 모습

 

그림 15의 SendMessageA를 spy++로 메세지로그를 캡쳐 후 동일하게 에뮬레이팅 후 아래코드와 같이 포팅하여 동작시켜본 결과 동일한 결과를 얻을 수 있었으나 아래 코드를 사용하지는 않는다. 어차피 webctrl컨드롤에서 전부 알아서 해주니까..

def send_msg_to_fdl(file_id, order_id, ftp):

    logger.debug(get_trace_this_point(9))

    """

    0#<8641664#<2985849#<R

    """

    fileis_hwnd = win32gui.FindWindow("Fileis_class_down", None)

 

    if fileis_hwnd <= 0:

        logger.debug("Not Found Fileis Downloader!!")

        return -1

 

    if len(str(file_id).strip()) <= 0 or len(str(order_id).strip()) <= 0:

        logger.debug("File id and order id should be inputted!!")

        return -1

 

    class CDS(Structure):

        _fields_ = [

            ("dwData", c_void_p),

            ("cbData", c_ulong),

            ("lpData", c_char_p)

            ]

 

    msg = u"0#" + str(file_id) + u"#<" + str(order_id) + u"#<" + str(ftp)

    print(msg)

    print(type(msg))

    msg = bytes(msg, "ms949")

    print(msg)

    print(type(msg))

 

    msg_buf = create_string_buffer(msg)

    print(msg_buf)

    msg_adrs = CDS(0, len(msg_buf), msg_buf.raw)

    print(msg_adrs)

    win32api.SendMessage(fileis_hwnd, win32con.WM_COPYDATA, 0, addressof(msg_adrs))

 

    return 0

 

위의 내용으로 다운로드 모듈의 분석은 종료하며, 추후 시간이되면 다운로드모듈 분석중 발견한 파일이즈 웹하드의 그리드웨어(컴퓨터 리소스 도둑!!)에 대한 부분도 추가토록 하겠다.. 하지만 귀찮아서 아마도... 안하지 않을까... 라는 뭐 그런...... 갱장히 귀찮고 무슨 부귀영화를 누리려고 이러나 싶기도 하고... 머 그냥 알았고 제거했으면 그만인것을.... 암튼 요 숭악무도한 놈이 자행하는 일은 아래와 같다.

그림16. NATservice라는 그리드웨어를 파일이즈 다운로드런처 설치시 몰래 설치해 논 모습

 

저렇게 NATService라는 놈으로 윈도 서비스에도 등록해놓고 방화벽에도 예외로 모든 포트를 개방해놓으며, 은제 으디서던 접근 할 수 있도록 항시 포트를 열고 대기를 하시는 패기넘치는 녀석이시다.. 요놈이 하는 행위와 삭제, 차단 방법은 난제 시간이 나면 공유토록 하겠다.

 

이제 전용브라우저의 간단한 구조를 설명하고 종료해야겠다 너무 길고 힘들고 구찮다... ㅋㅋㅋ 나머진 아래 첨부한 소스 까보시고 혹시 궁금하거나 잘못되어 있거나 이건 뭐 엉망이구나 하는 부분들은 빅태클 주시면 대환영 하겠습니다요.. 뉘예뉘예.. ㅡㅡ;;

 

전용브라우저는 간단하다.. 

1. 로컬 프록시 웹서버를 구성(FiddlerCord.dll) 후 

2. fileis.com 호스트로 오고 가는 모든 요청/응답을 중간에서 가로채서

3. 필요한 스크립트, html소스를 나의 입맛에 맞는 양념을 가미하고, 필요없는 부분을 제거하여 샤샥 원래의 장소로 전송해준다.

요게 끝!! ㅡㅡ;;

 

아아.... 

 

0x06. 소스

  미구현 기능이 있어 풀소스는 6월 둘째주 공개예정 : 동시(1분안쪽 1분이후는 상관없음)에 여러사람이 같은 파일(동일파일ID)을 다운로드 받을 시 선착순 1번을 빼고 나머지사람들의 요청은 영원히 묵살되는 치명적 오류 수정예정 ㅜㅜ

 

현재기준 소스: https://gist.github.com/helloong/e668eb5d1bdb823ef88958a65fba19da

 

 

'Study > python' 카테고리의 다른 글

[연습]모두의 경영 헬퍼  (0) 2015.09.14
[펌]Python code coverage for Lib/ctypes/wintypes.py  (0) 2014.10.12
shutil copyfileobj ()  (0) 2014.09.03
[연습]AutoPOKO ~~  (0) 2013.11.11
[펌]python thread 사용예  (0) 2013.10.16
Posted by 땡보
2015. 9. 14. 15:46

python opencv 및 image processing 학습겸 놀이겸 겸사겸사 만들어 본.. 모경.. 헬퍼..

갈길이 멀구나....


Test device : Samsung GalaxyPlayer5.8 (장비가 많이 옛날거라 버벅거림이 심하네요..)


혹여나 해서 적습니다.

순전히 개인적인 용도이며, 테스트 이외의 목적으로 사용하지 않습니다. 또한 배포도 없으며, 

다른분들의 민감한 정보들은 최대한 모자이크 처리 하였습니다. 

그래도.. 그래도... 문제가 된다면... 자삭 하겠습니다.

'Study > python' 카테고리의 다른 글

[연습]올파일포유?? ㅋㅋ  (0) 2018.05.11
[펌]Python code coverage for Lib/ctypes/wintypes.py  (0) 2014.10.12
shutil copyfileobj ()  (0) 2014.09.03
[연습]AutoPOKO ~~  (0) 2013.11.11
[펌]python thread 사용예  (0) 2013.10.16
Posted by 땡보
2014. 10. 12. 14:51

원문 LINK : http://coverage.livinglogic.de/Lib/ctypes/wintypes.py.html

Python code coverage for Lib/ctypes/wintypes.py

#countcontent
1n/a# The most useful windows datatypes
2n/aimport ctypes
3n/a
4n/aBYTE = ctypes.c_byte
5n/aWORD = ctypes.c_ushort
6n/aDWORD = ctypes.c_ulong
7n/a
8n/a#UCHAR = ctypes.c_uchar
9n/aCHAR = ctypes.c_char
10n/aWCHAR = ctypes.c_wchar
11n/aUINT = ctypes.c_uint
12n/aINT = ctypes.c_int
13n/a
14n/aDOUBLE = ctypes.c_double
15n/aFLOAT = ctypes.c_float
16n/a
17n/aBOOLEAN = BYTE
18n/aBOOL = ctypes.c_long
19n/a
20n/aclass VARIANT_BOOL(ctypes._SimpleCData):
21n/a _type_ = "v"
22n/a def __repr__(self):
23n/a return "%s(%r)" % (self.__class__.__name__, self.value)
24n/a
25n/aULONG = ctypes.c_ulong
26n/aLONG = ctypes.c_long
27n/a
28n/aUSHORT = ctypes.c_ushort
29n/aSHORT = ctypes.c_short
30n/a
31n/a# in the windows header files, these are structures.
32n/a_LARGE_INTEGER = LARGE_INTEGER = ctypes.c_longlong
33n/a_ULARGE_INTEGER = ULARGE_INTEGER = ctypes.c_ulonglong
34n/a
35n/aLPCOLESTR = LPOLESTR = OLESTR = ctypes.c_wchar_p
36n/aLPCWSTR = LPWSTR = ctypes.c_wchar_p
37n/aLPCSTR = LPSTR = ctypes.c_char_p
38n/aLPCVOID = LPVOID = ctypes.c_void_p
39n/a
40n/a# WPARAM is defined as UINT_PTR (unsigned type)
41n/a# LPARAM is defined as LONG_PTR (signed type)
42n/aif ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
43n/a WPARAM = ctypes.c_ulong
44n/a LPARAM = ctypes.c_long
45n/aelif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
46n/a WPARAM = ctypes.c_ulonglong
47n/a LPARAM = ctypes.c_longlong
48n/a
49n/aATOM = WORD
50n/aLANGID = WORD
51n/a
52n/aCOLORREF = DWORD
53n/aLGRPID = DWORD
54n/aLCTYPE = DWORD
55n/a
56n/aLCID = DWORD
57n/a
58n/a################################################################
59n/a# HANDLE types
60n/aHANDLE = ctypes.c_void_p # in the header files: void *
61n/a
62n/aHACCEL = HANDLE
63n/aHBITMAP = HANDLE
64n/aHBRUSH = HANDLE
65n/aHCOLORSPACE = HANDLE
66n/aHDC = HANDLE
67n/aHDESK = HANDLE
68n/aHDWP = HANDLE
69n/aHENHMETAFILE = HANDLE
70n/aHFONT = HANDLE
71n/aHGDIOBJ = HANDLE
72n/aHGLOBAL = HANDLE
73n/aHHOOK = HANDLE
74n/aHICON = HANDLE
75n/aHINSTANCE = HANDLE
76n/aHKEY = HANDLE
77n/aHKL = HANDLE
78n/aHLOCAL = HANDLE
79n/aHMENU = HANDLE
80n/aHMETAFILE = HANDLE
81n/aHMODULE = HANDLE
82n/aHMONITOR = HANDLE
83n/aHPALETTE = HANDLE
84n/aHPEN = HANDLE
85n/aHRGN = HANDLE
86n/aHRSRC = HANDLE
87n/aHSTR = HANDLE
88n/aHTASK = HANDLE
89n/aHWINSTA = HANDLE
90n/aHWND = HANDLE
91n/aSC_HANDLE = HANDLE
92n/aSERVICE_STATUS_HANDLE = HANDLE
93n/a
94n/a################################################################
95n/a# Some important structure definitions
96n/a
97n/aclass RECT(ctypes.Structure):
98n/a _fields_ = [("left", LONG),
99n/a ("top", LONG),
100n/a ("right", LONG),
101n/a ("bottom", LONG)]
102n/atagRECT = _RECTL = RECTL = RECT
103n/a
104n/aclass _SMALL_RECT(ctypes.Structure):
105n/a _fields_ = [('Left', SHORT),
106n/a ('Top', SHORT),
107n/a ('Right', SHORT),
108n/a ('Bottom', SHORT)]
109n/aSMALL_RECT = _SMALL_RECT
110n/a
111n/aclass _COORD(ctypes.Structure):
112n/a _fields_ = [('X', SHORT),
113n/a ('Y', SHORT)]
114n/a
115n/aclass POINT(ctypes.Structure):
116n/a _fields_ = [("x", LONG),
117n/a ("y", LONG)]
118n/atagPOINT = _POINTL = POINTL = POINT
119n/a
120n/aclass SIZE(ctypes.Structure):
121n/a _fields_ = [("cx", LONG),
122n/a ("cy", LONG)]
123n/atagSIZE = SIZEL = SIZE
124n/a
125n/adef RGB(red, green, blue):
126n/a return red + (green << 8) + (blue << 16)
127n/a
128n/aclass FILETIME(ctypes.Structure):
129n/a _fields_ = [("dwLowDateTime", DWORD),
130n/a ("dwHighDateTime", DWORD)]
131n/a_FILETIME = FILETIME
132n/a
133n/aclass MSG(ctypes.Structure):
134n/a _fields_ = [("hWnd", HWND),
135n/a ("message", UINT),
136n/a ("wParam", WPARAM),
137n/a ("lParam", LPARAM),
138n/a ("time", DWORD),
139n/a ("pt", POINT)]
140n/atagMSG = MSG
141n/aMAX_PATH = 260
142n/a
143n/aclass WIN32_FIND_DATAA(ctypes.Structure):
144n/a _fields_ = [("dwFileAttributes", DWORD),
145n/a ("ftCreationTime", FILETIME),
146n/a ("ftLastAccessTime", FILETIME),
147n/a ("ftLastWriteTime", FILETIME),
148n/a ("nFileSizeHigh", DWORD),
149n/a ("nFileSizeLow", DWORD),
150n/a ("dwReserved0", DWORD),
151n/a ("dwReserved1", DWORD),
152n/a ("cFileName", CHAR * MAX_PATH),
153n/a ("cAlternateFileName", CHAR * 14)]
154n/a
155n/aclass WIN32_FIND_DATAW(ctypes.Structure):
156n/a _fields_ = [("dwFileAttributes", DWORD),
157n/a ("ftCreationTime", FILETIME),
158n/a ("ftLastAccessTime", FILETIME),
159n/a ("ftLastWriteTime", FILETIME),
160n/a ("nFileSizeHigh", DWORD),
161n/a ("nFileSizeLow", DWORD),
162n/a ("dwReserved0", DWORD),
163n/a ("dwReserved1", DWORD),
164n/a ("cFileName", WCHAR * MAX_PATH),
165n/a ("cAlternateFileName", WCHAR * 14)]
166n/a
167n/a################################################################
168n/a# Pointer types
169n/a
170n/aLPBOOL = PBOOL = ctypes.POINTER(BOOL)
171n/aPBOOLEAN = ctypes.POINTER(BOOLEAN)
172n/aLPBYTE = PBYTE = ctypes.POINTER(BYTE)
173n/aPCHAR = ctypes.POINTER(CHAR)
174n/aLPCOLORREF = ctypes.POINTER(COLORREF)
175n/aLPDWORD = PDWORD = ctypes.POINTER(DWORD)
176n/aLPFILETIME = PFILETIME = ctypes.POINTER(FILETIME)
177n/aPFLOAT = ctypes.POINTER(FLOAT)
178n/aLPHANDLE = PHANDLE = ctypes.POINTER(HANDLE)
179n/aPHKEY = ctypes.POINTER(HKEY)
180n/aLPHKL = ctypes.POINTER(HKL)
181n/aLPINT = PINT = ctypes.POINTER(INT)
182n/aPLARGE_INTEGER = ctypes.POINTER(LARGE_INTEGER)
183n/aPLCID = ctypes.POINTER(LCID)
184n/aLPLONG = PLONG = ctypes.POINTER(LONG)
185n/aLPMSG = PMSG = ctypes.POINTER(MSG)
186n/aLPPOINT = PPOINT = ctypes.POINTER(POINT)
187n/aPPOINTL = ctypes.POINTER(POINTL)
188n/aLPRECT = PRECT = ctypes.POINTER(RECT)
189n/aLPRECTL = PRECTL = ctypes.POINTER(RECTL)
190n/aLPSC_HANDLE = ctypes.POINTER(SC_HANDLE)
191n/aPSHORT = ctypes.POINTER(SHORT)
192n/aLPSIZE = PSIZE = ctypes.POINTER(SIZE)
193n/aLPSIZEL = PSIZEL = ctypes.POINTER(SIZEL)
194n/aPSMALL_RECT = ctypes.POINTER(SMALL_RECT)
195n/aLPUINT = PUINT = ctypes.POINTER(UINT)
196n/aPULARGE_INTEGER = ctypes.POINTER(ULARGE_INTEGER)
197n/aPULONG = ctypes.POINTER(ULONG)
198n/aPUSHORT = ctypes.POINTER(USHORT)
199n/aPWCHAR = ctypes.POINTER(WCHAR)
200n/aLPWIN32_FIND_DATAA = PWIN32_FIND_DATAA = ctypes.POINTER(WIN32_FIND_DATAA)
201n/aLPWIN32_FIND_DATAW = PWIN32_FIND_DATAW = ctypes.POINTER(WIN32_FIND_DATAW)
202n/aLPWORD = PWORD = ctypes.POINTER(WORD)


'Study > python' 카테고리의 다른 글

[연습]올파일포유?? ㅋㅋ  (0) 2018.05.11
[연습]모두의 경영 헬퍼  (0) 2015.09.14
shutil copyfileobj ()  (0) 2014.09.03
[연습]AutoPOKO ~~  (0) 2013.11.11
[펌]python thread 사용예  (0) 2013.10.16
Posted by 땡보
2014. 9. 3. 08:07
shutil.copyfileobj(fsrc, fdst[, length])
Copy the contents of the file-like object fsrc to the file-like object fdst. The integer length, if given, is the buffer size. In particular, a negative length value means to copy the data without looping over the source data in chunks; by default the data is read in chunks to avoid uncontrolled memory consumption. Note that if
the current file position of the fsrc object is not 0, only the contents from the current file position to the end of the file will be copied.

'Study > python' 카테고리의 다른 글

[연습]모두의 경영 헬퍼  (0) 2015.09.14
[펌]Python code coverage for Lib/ctypes/wintypes.py  (0) 2014.10.12
[연습]AutoPOKO ~~  (0) 2013.11.11
[펌]python thread 사용예  (0) 2013.10.16
[연습]wxpython rss reader  (0) 2013.10.06
Posted by 땡보
2013. 11. 11. 01:38


최종 : 

POKO_Auto.py

#!/usr/bin/env python

#-*- coding:utf-8 -*-


import commands

import sys

import time

import os

import thread

from time import localtime, strftime

from datetime import datetime, timedelta


from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage


# global veriable definition

blockrange = [['B', [-2697555,-2169923,-5915996,-14585436,-11887922,-1641489,-13526322,-3809298,-15716030,-9192722,-15716022,-14590580,-14588532,-11360546,-14589564,-14589556,-4334618,-13532739,-14058059,-15122086,-15121053,-11296042,-14055747,-13532747,-13531459,-10245410,-13533515,-525313,-14582091,-9194794,-14057803,-5913939,-7027994,-13531715,-11888946,-14057035,-11887914,-8601882,-15713974,-15123118,-15713966,-14592653,-15117965,-15124142,-16242374,-13529395,-12413226,-13527346,-15717318,-15717054,-15717310,-15718342,-15717062,-16242630,-15718086,-10244386,-13527338,-13529394,-14054715,-13528370,-13530427,-13529403,-13003050,-13002026,-13002018,-13001002,-12937514,-12936490]],

              ['G', [-2168907,-526370,-527410,-9204216,-9205240,-7029240,-7034319,-9204208,-6507999,-1642564,-13550328,-9205232,-10256880,-3811701,-10258168,-9731568,-15130624,-9730544,-14605304,-10258160,-5914071,-10783480,-529524,-9796600,-13551352,-10850040,-4335765,-14075640,-10851056,-10259184,-10259192,-10849016,-4339110,-3811477,-7557607,-1051698,-2168907,-2167892,-4341158,-3745949,-1646716,-4338069,-14076672,-9201136,-8676848,-7033319,-8151536,-8675824,-9203184,-7558639,-12957432,-8677880,-12958464,-13548280,-8678896,-6506951,-9203192,-7031247,-13023992,-12958456,-7556600,-6503919,-13549304,-14077688,-7557599,-14077696,-4335773,-13552376,-14076664,-5979615,-3219580,-4861101,-12431096,-12432120,-12432112,-8084976,-6503920,-6504952,-8083952,-8082928,-7573026,-7559664,-7558640,-7557616,-7556592,-7032304,-7031288,-7031280,-7030264,-7030256,-6504944]],

              ['P', [-3836475,-4888131,-5413451,-1649681,-532555,-2713898,-3835443,-529442,-9220749,-6005340,-8105588,-12441278,-8698493,-12441534,-8106620,-4360771,-3241514,-1123602,-9222789,-9748109,-9222797,-2185506,-2181402,-1656090,-3832371,-2181426,-5411403,-529417,-4885059,-5937747,-4887115,-2711850,-4886091,-11915958,-11916206,-11915182,-11390638,-1126674,-1125650,-4888139,-11915950,-3307050,-530441,-11916214,-8105596,-8171133,-8172156,-8697469,-8697468,-8696444,-8696445,-8697469,-13557702,-1653010,-12442558,-13032390,-2183458,-3832114,-13557702,-4361795,-3242282,-4359483,-3307058,-3240490,-2710818,-13033414,-12966854,-12967878,-3836219,-12967870,-12966846,-3240234,-1058833,-4359739,-3242290,-3766578,-2713890,-3835451,-4887107,-4362819,-4362811,-4361787,-4360763,-4360507,-3835442,-3835186,-3834162,-3833138,-3243314,-3241258,-2715946,-2714922,-2714914]],

              ['R', [-1144180,-1671556,-1136212,-1673604,-1150597,-535635,-7210,-1671813,-542019,-3255974,-1152653,-1147269,-8637135,-1669525,-8178374,-8177351,-540995,-6012598,-6534838,-11394007,-6539966,-5416614,-2726557,-6538942,-1669492,-6537918,-1672845,-6536886,-6536894,-1676941,-2206374,-2203285,-2201237,-1073507,-544124,-2200981,-5430223,-1079676,-545108,-2200213,-2729629,-2727581,-2728605,-2725525,-3254950,-3844773,-1674885,-3845806,-3845798,-3845798,-2729638,-3845798,-1074539,-1675925,-10867407,-10868439,-1675917,-10868695,-2203293,-10869719,-11919327,-1148549,-11920351,-12443615,-12444639,-10278863,-10277839,-1080965,-1671557,-1672837,-1673613,-1672837,-1676949,-2735790,-2206373,-2205341,-2204317,-2202261,-1680029,-1680021,-1679005,-1678997,-1677973,-1674893,-1673869,-1149581,-1149573,-1147525,-1146501,-1081989]],

              ['Y', [-3830256,-12438264,-3114,-3238392,-2188784,-1057925,-11913984,-6524664,-1658303,-1651110,-535949,-6523640,-6524656,-532621,-11912952,-2190832,-6525688,-2187759,-1652191,-1124708,-2707952,-2708942,-532861,-2186727,-3238384,-2180592,-1651068,-3304944,-2180600,-5414648,-3239408,-532563,-536973,-3237360,-1657278,-2184679,-2182640,-11915000,-531581,-1129877,-10861304,-529467,-10863352,-10862328,-1127813,-1656279,-1658352,-1651934,-11913976,-12438272,-12439296,-1654255,-12439288,-12439288,-1655280,-2187760,-2186736,-2185712,-2184688,-2183664,-2181616,-1660400,-1659376,-1657328,-1656304,-1654264,-1654256,-1653232]],

              ['S', [-10276542,-6013630,-9744012,-7585470,-50862,-46749,-4364883,-45717,-44693]],

              ['F', [-15133680,-11913927,-11912903,-11386558,-14608359,-15133671,-11912902,-14607327,-11910846,-12438214,-11911870]],

              ['A', [-8625664,-10794744,-7046648,-11914992,-6521592,-7636728,-8689400,-4351480,-11914224,-4350456,-10732024,-11255544,-12965624,-12442352,-12441592,-9153024,-8105703,-5413599]]]


gamepan = [['',72,590,[1,8,7]],['',170,535,[2,8,0]],['',265,590,[3,10,9,8,1]],['',360,535,[4,10,2]],['',457,590,[5,12,11,10,3]],['',552,535,[6,12,4]],['',650,590,[13,12,5]],

           ['',72,700,[0,8,15,14]],['',170,645,[2,9,15,7,0,1]],['',265,700,[10,17,16,15,8,2]],['',360,645,[4,11,17,9,2,3]],['',457,700,[12,19,18,17,10,4]],['',552,645,[6,13,19,11,4,5]],['',650,700,[20,19,12,6]],

           ['',72,810,[7,15,22,21]],['',170,755,[9,16,22,14,7,8]],['',265,810,[17,24,23,22,15,9]],['',360,755,[11,18,24,16,9,10]],['',457,810,[19,26,25,24,17,11]],['',552,755,[13,20,26,18,11,12]],['',650,810,[27,26,19,13]],

           ['',72,920,[14,22,29,28]],['',170,865,[16,23,29,21,14,15]],['',265,920,[24,31,30,29,22,16]],['',360,865,[18,25,31,23,16,17]],['',457,920,[26,33,32,31,24,18]],['',552,865,[20,27,33,25,18,19]],['',650,920,[34,33,26,20]],

           ['',72,1030,[21,29,36,35]],['',170,975,[23,30,36,28,21,22]],['',265,1030,[31,38,37,36,29,23]],['',360,975,[25,32,38,30,23,24]],['',457,1030,[33,40,39,38,31,25]],['',552,975,[27,34,40,32,25,26]],['',650,1030,[41,40,33,27]],

           ['',72,1140,[28,36]],['',170,1085,[35,28,29,30,37]],['',265,1140,[36,30,38]],['',360,1085,[37,30,31,32,39]],['',457,1140,[38,32,40]],['',552,1085,[39,32,33,34,41]],['',650,1140,[40,34]]]


try:

    # connection to the current device, and return a MonkeyDevice object

    print "Please connect your device to your PC!!"

    device = MonkeyRunner.waitForConnection()


    def ChkAppState():

        AppInstall = device.shell('pm path com.nhncorp.SKPOCO')

        if AppInstall.startswith('package:'):

            print "POKOPANG is already installed."

        else:

            print "You should have install POKOPANG from google play."

            print "Process will be terminated."

            sys.exit(0)


        ChkAppLaunched = device.shell('ps')


        if ChkAppLaunched.find('com.nhncorp.SKPOCO'):

            print "POKOPANG is already launched!!"

            print "Kill exist process of POKOPANG!!"

            device.shell("am force-stop com.nhncorp.SKPOCO")

            MonkeyRunner.sleep(2)


        print "Launching POKOPANG..."

        device.startActivity(component='com.nhncorp.SKPOCO/com.treenod.android.UnityPlayerActivity')

        # Launching Pokopang.. in my device!!

        # device.touch(270, 600, MonkeyDevice.DOWN_AND_UP)

        # MonkeyRunner.sleep(1)

        # device.touch(440, 780, MonkeyDevice.DOWN_AND_UP)

        # MonkeyRunner.sleep(20)


    def TSS():

        try:

            while True:

                os.system('adb shell /system/bin/screencap -p /sdcard/tempscshot.png')

                os.system('adb pull /sdcard/tempscshot.png tempscshot.png')

                #ResultImage = device.takeSnapshot()

                ResultImage = MonkeyRunner.loadImageFromFile("tempscshot.png")

                if ResultImage:

                    return ResultImage

                    break

                else:

                    pass

        except Exception, e:

            print e.message, e.duration

            print "Error occur in takeSnapshot"

            sys.exit(-1)


    def IsNumber(s):

        try:

            float(s)

            return True

        except ValueError:

            return False


    def RtAddTime(sec):

        tempdt = datetime.now() + timedelta(seconds=sec)

        return tempdt.strftime("%Y%m%d.%H%M%S")


    def GetTimeFromNTP(ntpserver):

        nowtime = device.shell('rdate -sp ' + ntpserver)

        date_object = datetime.strptime(str(nowtime), "%a %b %d %I:%M:%S %Y")

        date_object = date_object + timedelta(seconds=32400)

        return date_object.strftime("%Y%m%d.%H%M%S")


    def SetDeviceTime(dtstr):

        f = open('tempdate.dat', 'w')

        f.write(dtstr)

        f.close()

        os.system('adb push tempdate.dat /sdcard/tempdate.dat')

        retval = device.shell("su -c 'sh ./sdcard/myshell.sh'")

        print str(retval)

        print "SetDeviceTime to " + str(dtstr)


    def ReChargeClover():

        # 277,237 ==> -7021766(Green clover) -9222896(No clover)

        cnt = 1

        while True:

            if TSS().getRawPixelInt(277, 237) == -7021766:

                print "Recharging complete!!"

                break

            print "Now Time : " + datetime.now().strftime("%Y%m%d.%H%M%S")

            SetDeviceTime(RtAddTime(360*cnt))

            print "After add(360sec) time : " + datetime.now().strftime("%Y%m%d.%H%M%S")

            cnt += 1

            MonkeyRunner.sleep(1)


    def ChkCell(id, idx, bidx, dragpaths, dragedpaths):


        childcells = gamepan[idx][3]

        #print "ID[" + str(idx) + "] childcell : " +  str(childcells)


        dragpaths[id].append(idx)


        for childcell in childcells:

            if childcell in dragpaths[id]:

                continue

            if gamepan[idx][0] == gamepan[childcell][0]:

                ChkCell(id, childcell, idx, dragpaths, dragedpaths)

                if id == idx:

                    if len(dragpaths[id]) >= 3:

                        dragedpaths.append(dragpaths[id])

                        dragpaths[id] = []

                        dragpaths[id].append(idx)

                    else:

                        dragpaths[id] = []

                        dragpaths[id].append(idx)


    def PlayGame():

        

        while True:

            print "Rescan!!"

            RstImg = TSS()

            dragpaths = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]

            dragedpaths = []

            sumofelement = []


            for idx in range(0,len(gamepan)):

                gamepan[idx][0] = RstImg.getRawPixelInt(gamepan[idx][1], gamepan[idx][2])

                #print "IDX[" + str(idx) + "]:" + str(gamepan[idx][0])


            #print gamepan

            for idx in range(0,len(gamepan)):

                for idx2 in range(0,len(blockrange)):

                    if gamepan[idx][0] in blockrange[idx2][1]:

                        gamepan[idx][0] = blockrange[idx2][0]


            notfoundcnt = 0

            for idx in range(0,len(gamepan)):

                if IsNumber(gamepan[idx][0]):

                    print "IDX[" + str(idx) + "]:" + str(gamepan[idx][0])

                    #RstImg.getSubImage((gamepan[idx][1]-30,gamepan[idx][2]-30,60,60)).writeToFile(strftime("%Y%M%d_%H%M", localtime()) + "_" + str(idx) + str(gamepan[idx][0]) + ".png")

                    notfoundcnt += 1

            #print gamepan


            if notfoundcnt >= 35:

                print "Not recognized more then 35 blocks!! maybe the game is over!!"

                break


            for idx in range(0, len(gamepan)):

                thread.start_new_thread(ChkCell,(idx, idx, -1, dragpaths, dragedpaths))


            #print "dragedpaths : " + str(dragedpaths)

            

            for idx in range(0, len(dragedpaths)):

                if sum(dragedpaths[idx]) in sumofelement:

                    print "maybe this element(" + str(dragedpaths[idx]) + ") is already dragged so we will skip it!!"

                    continue

                else:

                    sumofelement.append(sum(dragedpaths[idx]))

                    

                device.touch(gamepan[dragedpaths[idx][0]][1], gamepan[dragedpaths[idx][0]][2], MonkeyDevice.DOWN)

                MonkeyRunner.sleep(0.04)

                print "\nDrag Path : ",

                for node in dragedpaths[idx]:

                    print str(node),

                    device.touch(gamepan[node][1], gamepan[node][2], MonkeyDevice.MOVE)

                    MonkeyRunner.sleep(0.04)

                device.touch(gamepan[node][1], gamepan[node][2], MonkeyDevice.UP)

                MonkeyRunner.sleep(0.04)

                print " "


            for idx in range(0, len(gamepan)):

                device.touch(gamepan[idx][1], gamepan[idx][2], MonkeyDevice.DOWN_AND_UP)

                MonkeyRunner.sleep(0.03)


    def main():

        # starting script

        print "POKOPANG starting..."


        """

        device.touch(185, 1075, MonkeyDevice.DOWN_AND_UP)

        MonkeyRunner.sleep(1)

        """

        """

        print TSS().getRawPixelInt(660, 420)

        print device.takeSnapshot().getRawPixelInt(355, 1240)

        sys.exit(0)

        """

        

        # Check the state of POKOPANG

        ChkAppState()


        chk_time = 0

        while True:

            if TSS().getRawPixelInt(60, 240) == -4892416:

                print "Launching is complete!!"

                MonkeyRunner.sleep(1)

                skipnotice = False

                break

            else:

                print "Waiting for Launch..."

                MonkeyRunner.sleep(1)

                if TSS().getRawPixelInt(60, 240) == -4327573:

                    chk_time = chk_time + 1

                    if chk_time >= 3:

                        skipnotice = True

                        break


        if skipnotice == False:

            # Check Notice popup and close it!!

            print "Check daily notice!! and close it all!"

            while True:

                if TSS().getRawPixelInt(60, 240) == -4892416:

                    # Notice

                    # -4892416

                    # 600, 250

                    device.touch(600, 250, MonkeyDevice.DOWN_AND_UP)

                    MonkeyRunner.sleep(1)

                    Chk_Time = 0

                else:

                    if Chk_Time <= 3:

                        Chk_Time = Chk_Time + 1

                        MonkeyRunner.sleep(0.5)

                    else:

                        #MonkeyRunner.sleep(1)

                        break


        # Start of main cycle

        while True:

            print "Start of main cycle!!"

            while True:

                TSS_IMG = TSS()

                #getRawPixelInt(277, 237) == -10592064:

                #if TSS_IMG.getRawPixelInt(60, 240) == -4327573 and TSS_IMG.getRawPixelInt(670, 1130) == -4892416:

                if TSS_IMG.getRawPixelInt(277, 237) == -7021766 and TSS_IMG.getRawPixelInt(670, 1130) == -4892416:

                    print "It is ok to play game!!"

                    # To go to play game

                    # 350, 1070

                    break

                else:

                    device.touch(355, 1240, MonkeyDevice.DOWN_AND_UP)

                    print "Wait a moment and Rechanging clover!!"

                    if TSS_IMG.getRawPixelInt(670, 1130) == -4892416:

                        ReChargeClover()

                        SetDeviceTime(GetTimeFromNTP('time.bora.net'))

                    # Wait For time

                    MonkeyRunner.sleep(10)


            device.touch(350, 1070, MonkeyDevice.DOWN_AND_UP)

            MonkeyRunner.sleep(1)

            device.touch(350, 1070, MonkeyDevice.DOWN_AND_UP)

            MonkeyRunner.sleep(2)


            Chk_Time = 0

            while True:

                if TSS().getRawPixelInt(660, 420) == -4892416:

                    print "Help notice is showed!!"

                    device.touch(195, 960, MonkeyDevice.DOWN_AND_UP)

                    MonkeyRunner.sleep(1)

                else:

                    if Chk_Time <= 3:

                        Chk_Time = Chk_Time + 1

                        MonkeyRunner.sleep(0.5)

                    else:

                        break


            # -56246

            while True:

                #if TSS().getRawPixelInt(30, 45) == -56246:

                #if TSS().getRawPixelInt(660, 420) != -4892416:

                #if TSS().getRawPixelInt(678, 1100) not in (-16777024, -4892416, -7590623, -16736410):

                if TSS().getRawPixelInt(27, 1144) not in (-9225984, -7058168, -15135744, -7584504, -7585536, -14609400, -4360919, -14083056):

                    print "Game is playing!!"

                    PlayGame()

                    MonkeyRunner.sleep(1)

                else:

                    print "Game over!!"

                    Chk_Time = 0

                    while True:

                        if TSS().getRawPixelInt(27, 1144) != -9225984:

                            if TSS().getRawPixelInt(27, 1144) == -14609400:

                                print "Close monster info!"

                                device.touch(350, 880, MonkeyDevice.DOWN_AND_UP)

                                MonkeyRunner.sleep(1)

                            if TSS().getRawPixelInt(27, 1144) == -7058168:

                                print "Close monster list!"

                                device.touch(630, 230, MonkeyDevice.DOWN_AND_UP)

                                MonkeyRunner.sleep(1)

                            if TSS().getRawPixelInt(27, 1144) == -15135744:

                                print "Close mission info!"

                                device.touch(360, 800, MonkeyDevice.DOWN_AND_UP)

                                MonkeyRunner.sleep(1)

                            if TSS().getRawPixelInt(27, 1144) == -7584504:

                                if TSS().getRawPixelInt(150, 630) == -3240407:

                                    print "Close item store!"

                                    device.touch(630, 330, MonkeyDevice.DOWN_AND_UP)

                                    MonkeyRunner.sleep(1)

                            if TSS().getRawPixelInt(27, 1144) == -7585536:

                                print "Close upgrade shop!"

                                device.touch(630, 330, MonkeyDevice.DOWN_AND_UP)

                                MonkeyRunner.sleep(1)

                            if TSS().getRawPixelInt(27, 1144) == -14083056:

                                if TSS().getRawPixelInt(150, 630) == -10249728:

                                    print "Close send clover info!"

                                    device.touch(360, 800, MonkeyDevice.DOWN_AND_UP)

                                    MonkeyRunner.sleep(1)

                                if TSS().getRawPixelInt(150, 630) == -10249728:

                                    print "Close send clover info!"

                                    device.touch(360, 800, MonkeyDevice.DOWN_AND_UP)

                                    MonkeyRunner.sleep(1)

                                if TSS().getRawPixelInt(150, 630) == -14053715:

                                    print "Close today mission window!"

                                    device.touch(360, 800, MonkeyDevice.DOWN_AND_UP)

                                    MonkeyRunner.sleep(1)

                                if TSS().getRawPixelInt(150, 630) == -7060224:

                                    print "Close profile!"

                                    device.touch(355, 915, MonkeyDevice.DOWN_AND_UP)

                                    MonkeyRunner.sleep(1)

                            if TSS().getRawPixelInt(27, 1144) == -4360919:

                                break

                        else:

                            if Chk_Time <= 3:

                                Chk_Time = Chk_Time + 1

                                MonkeyRunner.sleep(0.5)

                            else:

                                break

                    MonkeyRunner.sleep(1)

                    break


            # 40, 945 ==> -10859455 ==> 645, 970

            while TSS().getRawPixelInt(660, 420) == -4892416:

                # Add Time Notice or High score notice!!

                device.touch(195, 960, MonkeyDevice.DOWN_AND_UP)

                MonkeyRunner.sleep(1)

                

                while True:

                    if TSS().getRawPixelInt(40, 945) == -10859455:

                        print "Notice pop up!!"

                        device.touch(665, 947, MonkeyDevice.DOWN_AND_UP)

                        MonkeyRunner.sleep(1)

                    else:

                        print "Notice is not exists!!"

                        break


                # 40, 945 ==> -4892416 ==> 185, 1075

                while True:

                    if TSS().getRawPixelInt(40, 945) == -4892416:

                        print "Game score pop up!!"

                        device.touch(185, 1075, MonkeyDevice.DOWN_AND_UP)

                        MonkeyRunner.sleep(1)

                    else:

                        print "Game score popup is closed!!"

                        MonkeyRunner.sleep(1)

                        break


            print "End of main cycle.."

            print "Restarting..."



    if __name__ == "__main__":

        main()

finally:

    device.shell("am force-stop com.android.commands.monkey")




2013-11-13


jython_test0001.py


jython_test0002.py


POKO_Auto.py


POKO_Auto_Fin.py


test001.py

포코팡오토_색상변위표.xlsx


older_version

POKO_Auto.py


'Study > python' 카테고리의 다른 글

[펌]Python code coverage for Lib/ctypes/wintypes.py  (0) 2014.10.12
shutil copyfileobj ()  (0) 2014.09.03
[펌]python thread 사용예  (0) 2013.10.16
[연습]wxpython rss reader  (0) 2013.10.06
wxpython webview test  (0) 2013.10.05
Posted by 땡보
2013. 10. 16. 14:23



참고: http://docs.python.org/library/thread.html



1. 가장 기초적인 Thread

thread.start_new_thread(func, args, kwargs=None)
  func = thread 실행 함수
  args = func에 넘겨줄 인수
  kwargs = 키워드 인수

#!/usr/bin/python 
import thread, time

# thread에서 실행될 함수
def counter(id): 
    for in range(5):
        print 'id %s --> %s' % (id, i)
        time.sleep(0.1)

# thread 5개 실행
for 
in range(5):
    thread.start_new_thread(counter, (i,))

# thread가 다 돌 때까지 대기
time.sleep(1)
print 'Exiting'






2. Critical Section

thread.allocate_lock() : critical section에 사용할 lock 객체 리턴
lock.acquire() : lock을 건다
lock.release() : 걸었던 lock 해제
lock.locked() : lock이 걸려있는지 검사. 락이 걸려 있으면 True, 아니면 False

#!/usr/bin/python 
import thread, time

g_count = 0
# lock 객체 생성
lock = thread.allocate_lock()

def counter(id, count):
    global g_count
    for in range(count):
        print 'id %s --> %s' % (id, i)
        # lock 건다
        lock.acquire()
        # 전역변수 핸들링
        g_count = g_count + 1
        # lock 해제
        lock.release()

for in range(5):
    thread.start_new_thread(counter, (i, 5))

time.sleep(1)
print 'Total Count = ', g_count
print 'Exiting'







3. thread 종료 대기

#!/usr/bin/python
import thread, time

# 생성할 Thread 갯수 지정
NumberOfThread = 5
# 실행중인 Thread 갯수
ThreadsLeft = NumberOfThread

# Critical Section에 사용할 lock 객체 생성
lock = thread.allocate_lock()

# Thread 종료처리 함수
def threadexit(id):
    global ThreadsLeft
    print 'thread %d is quitting' % id
    lock.acquire()
    ThreadsLeft -= 1
    lock.release()


def counter(id, count):
    for in range(count):
        print 'id %s --> %s' % (id, i)
    threadexit(id) # thread 종료처리 함수 호출

# NumberOfThread 만큼 Thread 생성

for in range(NumberOfThread):
    thread.start_new_thread(counter, (i, 5))

# 모든 Thread가 종료될 때 까지 대기
while ThreadsLeft:
    time.sleep(0.1)

print 'Exiting'


thread 보다 객체지향적인 방법으로 사용가능한 thread 객체.
Delphi의 TThread와 유사한 형태.



1. 생성자에 직접 함수 전달

#!/usr/bin/python

import threading, time

def myThread(id):
    for in range(10):
        print 'id=%s --> %s' % (id, i)
        # CPU 양보
        time.sleep(0)

# thread 객체를 모아둘 리스트
threads = []

for in range(2):
    # myThread를 실행하는 thread 생성
    th = threading.Thread(target=myThread, args=(i,))
    # thread 시작
    th.start()
    # thread 객체리스트에 추가
    threads.append(th)

# thread 종료까지 대기
for th in threads:
    th.join()

print 'Exiting'







2. 서브클래스에서 run method 재정의
  (delphi의 TThread 클래스에서 Execute를 override해서 사용하는 방법과 유사함)

#!/usr/bin/python

import threading, time

# threading 상속
class MyThread(threading.Thread):
    # thread 실행본체인 run method 재정의
    def run(self):
        for in range(10):
            print 'id=%s --> %s' % (self.getName(), i) # self.getName은 Thread 이름 반환
            time.sleep(0)


threads = []

for in range(2):
    th = MyThread()
    th.start()
    threads.append(th)


for th in threads:
    th.join()

print 'Exiting'







3. Critical Section

#!/usr/bin/python 

import threading, time

# 전역변수
g_count = 0

class MyThread(threading.Thread)
    def run(self):
        global g_count
        for in range(10):
            # lock
            lock.acquire()
            # 전역변수 핸들링
            g_count += 1
            # 실제로 2개 이상의 Thread가 동시에 전역변수를 핸들링하도록 sleep
            time.sleep(0.1)
            # 어느 thread 가 전역변수를 어떻게 바꿨는지 print
            print '[%s] g_count = %s' % (self.getName(), g_count)
            # lock 해제
            lock.release()


# Lock 객체 생성
lock = threading.Lock()

threads = []

for in range(2):
    th = MyThread()
    th.start()
    threads.append(th)

for th in threads:
    th.join()

print 'TotalCount = ', g_count
print 'Exiting'





'Study > python' 카테고리의 다른 글

shutil copyfileobj ()  (0) 2014.09.03
[연습]AutoPOKO ~~  (0) 2013.11.11
[연습]wxpython rss reader  (0) 2013.10.06
wxpython webview test  (0) 2013.10.05
[연습중]MK RSS 파싱  (0) 2013.09.23
Posted by 땡보
2013. 10. 6. 16:01




setup.exe


wx_browsertest.py


2013.10.18 - final

#!/usr/bin/env python

#-*- coding:utf-8 -*-


from bs4 import BeautifulSoup

import wx

import wx.html2

import urllib2

import re

import thread

import time


news_url = u""


#----------------------------------------------------------------------

class ReaderPanel(wx.Panel):


    def __init__(self, parent):


        wx.Panel.__init__(self, parent)


        self.current = news_hosts[8]

        self.frame = self.GetTopLevelParent()

        self.titleBase = self.frame.GetTitle()


        sizer = wx.BoxSizer(wx.VERTICAL)

        

        grpSizer = wx.BoxSizer(wx.HORIZONTAL)

        

        st1 = wx.StaticText(self, label=u"뉴스카테고리 : ")

        grpSizer.Add(st1, 0, wx.CENTER|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"새로고침", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnReload, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"헤드라인", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo0, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"전체뉴스", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo1, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"경제", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo2, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"정치", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo3, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"사회", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo4, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"국제", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo5, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"기업경영", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo6, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"증권", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo7, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"부동산", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo8, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"문화연예", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo9, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"패션", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo10, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"스포츠", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo11, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"게임", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo12, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"오피니언", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo13, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        sizer.Add(grpSizer, 0, wx.EXPAND)

        

        sizer.Add((-1, 10))

        

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)


        #btn = wx.Button(self, -1, u"Open", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        #btn = wx.Button(self, -1, u"<--", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        #self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)


        #btn = wx.Button(self, -1, u"-->", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        #self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)


        #btn = wx.Button(self, -1, u"Stop", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        #btn = wx.Button(self, -1, u"Refresh", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        txt = wx.StaticText(self, -1, u"Location:")

        btnSizer.Add(txt, 0, wx.CENTER|wx.ALL, 2)


        self.location = wx.ComboBox(

            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)

        self.location.AppendItems([u"http://www.mk.co.kr/"])


        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)

        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)

        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)


        sizer.Add(btnSizer, 0, wx.EXPAND)

        

        sizer.Add((-1, 10))

        

        self.wv = wx.html2.WebView.New(self)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.OnWebViewNavigated, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)

        sizer.Add(self.wv, 1, wx.EXPAND)

        

        self.SetSizer(sizer)


        #self.wv.LoadURL(self.current)

        self.wv.SetPage(news_rss[8], news_hosts[8])

        


    # WebView events

    def OnWebViewNavigating(self, evt):

        # this event happens prior to trying to get a resource

        print u"OnWebViewNavigating URL is : %s" % evt.GetURL()

        #wx.MessageBox(evt.GetURL(), u"Target URL is...", wx.OK|wx.ICON_INFORMATION, self)

        # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

        if (u"http://mk.co.kr.feedsportal.com/c/" in evt.GetURL()) and (not u"/index.rss" in evt.GetURL()):

            news_url = evt.GetURL()

            news_script = SetPage(evt.GetURL(), u"MK")

            self.wv.SetPage(u"<html><div>" + news_script + u"</div></html>", news_url)

            evt.Veto()

            self.current = news_url

            self.location.SetString(0, self.current)

        elif (u"http://mk.co.kr.feedsportal.com/c/" in evt.GetURL()) and (u"/index.rss" in evt.GetURL()):

            news_url = evt.GetURL()

            news_script = SetPage(evt.GetURL(), u"TITLE")

            self.wv.SetPage(news_script, news_url)

            evt.Veto()

            self.current = news_url

            self.location.SetString(0, self.current)



    def OnWebViewNavigated(self, evt):

        self.frame.SetStatusText(u"Loading %s..." % evt.GetURL())


    def OnTestButton(self, evt):

        pass


    def OnWebViewLoaded(self, evt):

        # The full document has loaded

        self.current = evt.GetURL()

        if self.current == u"http:///":

            self.current = self.location.GetString(0)

            self.location.SetValue(self.location.GetString(0))

        else:

            self.location.SetValue(self.current)

        self.frame.SetStatusText(u"Loaded")

        #self.wv.RunScript("""alert('""" + self.current + """');""")

        #self.wv.RunScript("""

        #//call logIn();

        #//document.getElementsByName('q')[0].value="hist";

        #//document.getElementById('openididentifier').value="ident";

        #""")

        #self.wv.SetPage(self, """<html>하하하</html>""", """http://www.naver.com""")



    def OnWebViewTitleChanged(self, evt):

        # Set the frame's title to include the document's title

        self.frame.SetTitle("%s -- %s" % (self.titleBase, evt.GetString()))


    # Control bar events

    def OnLocationSelect(self, evt):

        url = self.location.GetStringSelection()

        print(u"OnLocationSelect: %s\n" % url)

        self.wv.LoadURL(url)


    def OnLocationEnter(self, evt):

        url = self.location.GetValue()

        self.location.Append(url)

        self.wv.LoadURL(url)


    def OnOpenButton(self, event):

        dlg = wx.TextEntryDialog(self, u"Input Url or local file path", u"URL", self.current, wx.OK|wx.CANCEL)

        dlg.CentreOnParent()


        if dlg.ShowModal() == wx.ID_OK:

            self.current = dlg.GetValue()

            self.wv.LoadURL(self.current)


        dlg.Destroy()


    def OnPrevPageButton(self, event):

        for i in self.wv.GetBackwardHistory():

            print i.Url, i.Title

        self.wv.GoBack()

        #self.wv.LoadURL(u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss")


    def OnNextPageButton(self, event):

        for i in self.wv.GetForwardHistory():

            print i.URL, i.Title

        self.wv.GoForward()


    def OnCheckCanGoBack(self, event):

        event.Enable(self.wv.CanGoBack())


    def OnCheckCanGoForward(self, event):

        event.Enable(self.wv.CanGoForward())


    def OnStopButton(self, evt):

        self.wv.Stop()


    def OnRefreshPageButton(self, evt):

        self.wv.Reload()


    def OnReload(self, evt):

        grap_news_title()

        self.current = news_hosts[8]

        self.wv.SetPage(news_rss[8], self.current)

        

    def OnGoTo0(self, evt):

        self.current = news_hosts[0]

        self.wv.SetPage(news_rss[0], self.current)

    

    def OnGoTo1(self, evt):

        self.current = news_hosts[1]

        self.wv.SetPage(news_rss[1], self.current)


    def OnGoTo2(self, evt):

        self.current = news_hosts[2]

        self.wv.SetPage(news_rss[2], self.current)

        

    def OnGoTo3(self, evt):

        self.current = news_hosts[3]

        self.wv.SetPage(news_rss[3], self.current)

    

    def OnGoTo4(self, evt):

        self.current = news_hosts[4]

        self.wv.SetPage(news_rss[4], self.current)

        

    def OnGoTo5(self, evt):

        self.current = news_hosts[5]

        self.wv.SetPage(news_rss[5], self.current)

        

    def OnGoTo6(self, evt):

        self.current = news_hosts[6]

        self.wv.SetPage(news_rss[6], self.current)

        

    def OnGoTo7(self, evt):

        self.current = news_hosts[7]

        self.wv.SetPage(news_rss[7], self.current)

        

    def OnGoTo8(self, evt):

        self.current = news_hosts[8]

        self.wv.SetPage(news_rss[8], self.current)

        

    def OnGoTo9(self, evt):

        self.current = news_hosts[9]

        self.wv.SetPage(news_rss[9], self.current)

        

    def OnGoTo10(self, evt):

        self.current = news_hosts[10]

        self.wv.SetPage(news_rss[10], self.current)

        

    def OnGoTo11(self, evt):

        self.current = news_hosts[11]

        self.wv.SetPage(news_rss[11], self.current)

        

    def OnGoTo12(self, evt):

        self.current = news_hosts[12]

        self.wv.SetPage(news_rss[12], self.current)

        

    def OnGoTo13(self, evt):

        self.current = news_hosts[13]

        self.wv.SetPage(news_rss[13], self.current)


#----------------------------------------------------------------------

def GetUrlSrc(as_url, as_decoding):

    html_src = urllib2.urlopen(as_url).read()

    return html_src.decode(as_decoding, 'ignore')


def SetPage(as_url, as_site, return_val=None, return_idx=None):

    ls_temp_header = u"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

                        <html xmlns="http://www.w3.org/1999/xhtml">

                        <head>

                        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

                        <style type="text/css">

                        body {

                            margin-left: 10px;

                            margin-top: 10px;

                            margin-right: 10px;

                            margin-bottom: 10px;

                        }

                        .news {

                            font-family: "돋움체";

                            font-size: 14px;

                        }

                        </style>

                        </head>

                        

                        <body>"""

                        

    ls_temp_footer = u"""</body></html>"""

    

    # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

    if as_site == u"MK":

        title_pattern = "<title>(.*?)</title>".decode("utf-8", "ignore")

        script_pattern = "<div\sclass=\'read_txt\'>(.*?)\s*?<!--이미지".decode("utf-8", "ignore")

        result_html = GetUrlSrc(as_url, u"cp949")

        #wx.MessageBox(result_html, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        result_text = re.findall(script_pattern, result_html, re.DOTALL)

        result_title = re.findall(title_pattern, result_html, re.DOTALL)

        print result_title

        if result_text:

            #wx.MessageBox(result_text[0], u"Test", wx.OK|wx.ICON_INFORMATION, self)

            #ls_return = " ".join(str(re.sub("<[^>]*>".decode("utf-8", "ignore"), "".decode("utf-8", "ignore"), result_text[0]).encode("cp949", "ignore")).split())

            #wx.MessageBox(result_text[0], u"News", wx.OK|wx.ICON_INFORMATION)

            return ls_temp_header + u"""<title>""" + result_title[0] + u"""</title>""" + result_text[0] + ls_temp_footer

    elif as_site == u"TITLE":

        html_src_uni = GetUrlSrc(as_url, 'utf-8')

        soup = BeautifulSoup(html_src_uni)

        ls_temp = str(soup('title')).decode('utf-8', 'ignore')

        pattern = u'<title>(.*?)</title>'

        ls_result_title = re.findall(pattern, ls_temp, re.DOTALL)

        ls_temp = str(soup('link')).decode('utf-8', 'ignore')

        pattern = u'<link>(.*?)</link>'

        ls_result_link = re.findall(pattern, ls_temp, re.DOTALL)

        ls_temp = str(soup('description')).decode('utf-8', 'ignore')

        ls_temp = ls_temp.replace(u'신문기사</description>', u'신문기사..&lt;img')

        pattern = u'<description>(.*?)..&lt;img'

        ls_result_description = re.findall(pattern, ls_temp, re.DOTALL)

        

        ls_temp_body_header = u"""<title>""" + ls_result_title[0] + u"""</title>""" + u"""<table width="1010" height="25" border="0" cellpadding="0" cellspacing="0"><tr><td width="1000" height="10" class="news">"""

        ls_temp_body_footer = u"""</a></td></tr></table>"""

        ls_temp_body = u""

        for ll_idx in range(len(ls_result_title)):

            if ll_idx == 0:

                continue

            ls_temp_body = ls_temp_body + ls_temp_body_header + str(ll_idx) + u" : " + u"""<a href=" """ + ls_result_link[ll_idx] + u""" ">""" + ls_result_title[ll_idx] + ls_temp_body_footer

        

        if return_val == None:

            return ls_temp_header + ls_temp_body + ls_temp_footer

        else:

            return_val[return_idx] = ls_temp_header + ls_temp_body + ls_temp_footer

            threadexit()


def threadexit():

    global threadsleft

    lock.acquire()

    threadsleft -= 1

    lock.release()


def grap_news_title():

    global threadsleft 

    

    threadsleft = len(news_hosts)

    print len(news_hosts)

    

    for i in range(len(news_hosts)):

        news_rss.append(u"")

        thread.start_new_thread(SetPage, (news_hosts[i], u"TITLE", news_rss, i ))

        

    while threadsleft:

        pass


def main():

    

    global news_rss, threadsleft, lock, news_hosts

    news_rss = [u""]

    lock = thread.allocate_lock()


    news_hosts = [u"http://mk.co.kr.feedsportal.com/c/34147/f/618372/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618373/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618374/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618375/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618376/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618377/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618378/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618379/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618381/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/651700/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/651701/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618383/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618384/index.rss"]


    start = time.time()

    

    grap_news_title()


    print time.time() - start

    

    app = wx.App()

    frm = wx.Frame(None, style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.FRAME_EX_METAL, title=u"MK_RSS Reader v0.9", size=(1048,768))

    frm.CreateStatusBar()

    ico = wx.Icon(u"MK_RSS.ico", wx.BITMAP_TYPE_ICO)

    frm.SetIcon(ico)

    pnl = ReaderPanel(frm)

    frm.Show()

    frm.Center()

    app.MainLoop()


#----------------------------------------------------------------------

if __name__ == '__main__':

    main()

2013.10.15

#!/usr/bin/env python

#-*- coding:utf-8 -*-


from bs4 import BeautifulSoup

import wx

import wx.html2

import urllib2

import re

import thread

import time


news_url = u""


#----------------------------------------------------------------------

class TestPanel(wx.Panel):


    def __init__(self, parent):


        wx.Panel.__init__(self, parent)


        self.current = news_hosts[8]

        self.frame = self.GetTopLevelParent()

        self.titleBase = self.frame.GetTitle()


        sizer = wx.BoxSizer(wx.VERTICAL)

        

        grpSizer = wx.BoxSizer(wx.HORIZONTAL)

        

        st1 = wx.StaticText(self, label='News Category : ')

        grpSizer.Add(st1, 0, wx.CENTER|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"헤드라인", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo0, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"전체뉴스", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo1, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"경제", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo2, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"정치", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo3, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"사회", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo4, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"국제", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo5, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"기업경영", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo6, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"증권", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo7, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"부동산", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo8, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"문화연예", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo9, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"패션", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo10, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"스포츠", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo11, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"게임", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo12, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"오피니언", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoTo13, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        sizer.Add(grpSizer, 0, wx.EXPAND)

        

        sizer.Add((-1, 10))

        

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)


        #btn = wx.Button(self, -1, u"Open", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        #btn = wx.Button(self, -1, u"<--", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        #self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)


        #btn = wx.Button(self, -1, u"-->", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        #self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)


        #btn = wx.Button(self, -1, u"Stop", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        #btn = wx.Button(self, -1, u"Refresh", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        txt = wx.StaticText(self, -1, u"Location:")

        btnSizer.Add(txt, 0, wx.CENTER|wx.ALL, 2)


        self.location = wx.ComboBox(

            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)

        self.location.AppendItems([u"http://www.mk.co.kr/"])


        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)

        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)

        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)


        sizer.Add(btnSizer, 0, wx.EXPAND)

        

        sizer.Add((-1, 10))

        

        self.wv = wx.html2.WebView.New(self)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.OnWebViewNavigated, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)

        sizer.Add(self.wv, 1, wx.EXPAND)

        

        self.SetSizer(sizer)


        #self.wv.LoadURL(self.current)

        self.wv.SetPage(news_rss[8], news_hosts[8])

        


    # WebView events

    def OnWebViewNavigating(self, evt):

        # this event happens prior to trying to get a resource

        print u"OnWebViewNavigating URL is : %s" % evt.GetURL()

        #wx.MessageBox(evt.GetURL(), u"Target URL is...", wx.OK|wx.ICON_INFORMATION, self)

        # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

        if (u"http://mk.co.kr.feedsportal.com/c/" in evt.GetURL()) and (not u"/index.rss" in evt.GetURL()):

            news_url = evt.GetURL()

            news_script = SetPage(evt.GetURL(), u"MK")

            self.wv.SetPage(u"<html><div>" + news_script + u"</div></html>", news_url)

            evt.Veto()

            self.current = news_url

            self.location.SetString(0, self.current)

        elif (u"http://mk.co.kr.feedsportal.com/c/" in evt.GetURL()) and (u"/index.rss" in evt.GetURL()):

            news_url = evt.GetURL()

            news_script = SetPage(evt.GetURL(), u"TITLE")

            self.wv.SetPage(news_script, news_url)

            evt.Veto()

            self.current = news_url

            self.location.SetString(0, self.current)



    def OnWebViewNavigated(self, evt):

        self.frame.SetStatusText(u"Loading %s..." % evt.GetURL())


    def OnTestButton(self, evt):

        pass


    def OnWebViewLoaded(self, evt):

        # The full document has loaded

        self.current = evt.GetURL()

        if self.current == u"http:///":

            self.current = self.location.GetString(0)

            self.location.SetValue(self.location.GetString(0))

        else:

            self.location.SetValue(self.current)

        self.frame.SetStatusText(u"Loaded")

        #self.wv.RunScript("""alert('""" + self.current + """');""")

        #self.wv.RunScript("""

        #//call logIn();

        #//document.getElementsByName('q')[0].value="hist";

        #//document.getElementById('openididentifier').value="ident";

        #""")

        #self.wv.SetPage(self, """<html>하하하</html>""", """http://www.naver.com""")



    def OnWebViewTitleChanged(self, evt):

        # Set the frame's title to include the document's title

        self.frame.SetTitle("%s -- %s" % (self.titleBase, evt.GetString()))


    # Control bar events

    def OnLocationSelect(self, evt):

        url = self.location.GetStringSelection()

        print(u"OnLocationSelect: %s\n" % url)

        self.wv.LoadURL(url)


    def OnLocationEnter(self, evt):

        url = self.location.GetValue()

        self.location.Append(url)

        self.wv.LoadURL(url)


    def OnOpenButton(self, event):

        dlg = wx.TextEntryDialog(self, u"Input Url or local file path", u"URL", self.current, wx.OK|wx.CANCEL)

        dlg.CentreOnParent()


        if dlg.ShowModal() == wx.ID_OK:

            self.current = dlg.GetValue()

            self.wv.LoadURL(self.current)


        dlg.Destroy()


    def OnPrevPageButton(self, event):

        for i in self.wv.GetBackwardHistory():

            print i.Url, i.Title

        self.wv.GoBack()

        #self.wv.LoadURL(u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss")


    def OnNextPageButton(self, event):

        for i in self.wv.GetForwardHistory():

            print i.URL, i.Title

        self.wv.GoForward()


    def OnCheckCanGoBack(self, event):

        event.Enable(self.wv.CanGoBack())


    def OnCheckCanGoForward(self, event):

        event.Enable(self.wv.CanGoForward())


    def OnStopButton(self, evt):

        self.wv.Stop()


    def OnRefreshPageButton(self, evt):

        self.wv.Reload()


    def OnGoTo0(self, evt):

        self.current = news_hosts[0]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[0], self.current)

    

    def OnGoTo1(self, evt):

        self.current = news_hosts[1]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[1], self.current)


    def OnGoTo2(self, evt):

        self.current = news_hosts[2]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[2], self.current)

        

    def OnGoTo3(self, evt):

        self.current = news_hosts[3]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[3], self.current)

    

    def OnGoTo4(self, evt):

        self.current = news_hosts[4]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[4], self.current)

        

    def OnGoTo5(self, evt):

        self.current = news_hosts[5]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[5], self.current)

        

    def OnGoTo6(self, evt):

        self.current = news_hosts[6]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[6], self.current)

        

    def OnGoTo7(self, evt):

        self.current = news_hosts[7]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[7], self.current)

        

    def OnGoTo8(self, evt):

        self.current = news_hosts[8]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[8], self.current)

        

    def OnGoTo9(self, evt):

        self.current = news_hosts[9]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[9], self.current)

        

    def OnGoTo10(self, evt):

        self.current = news_hosts[10]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[10], self.current)

        

    def OnGoTo11(self, evt):

        self.current = news_hosts[11]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[11], self.current)

        

    def OnGoTo12(self, evt):

        self.current = news_hosts[12]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[12], self.current)

        

    def OnGoTo13(self, evt):

        self.current = news_hosts[13]

        #self.wv.LoadURL(self.current)

        #wx.MessageBox(economy_rss, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        self.wv.SetPage(news_rss[13], self.current)


#----------------------------------------------------------------------

def GetUrlSrc(as_url, as_decoding):

    html_src = urllib2.urlopen(as_url).read()

    return html_src.decode(as_decoding, 'ignore')


def SetPage(as_url, as_site, return_val=None, return_idx=None):

    ls_temp_header = u"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

                        <html xmlns="http://www.w3.org/1999/xhtml">

                        <head>

                        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

                        <style type="text/css">

                        body {

                            margin-left: 10px;

                            margin-top: 10px;

                            margin-right: 10px;

                            margin-bottom: 10px;

                        }

                        .news {

                            font-family: "돋움체";

                            font-size: 14px;

                        }

                        </style>

                        </head>

                        

                        <body>"""

                        

    ls_temp_footer = u"""</body></html>"""

    

    # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

    if as_site == u"MK":

        title_pattern = "<title>(.*?)</title>".decode("utf-8", "ignore")

        script_pattern = "<div\sclass=\'read_txt\'>(.*?)\s*?<!--이미지".decode("utf-8", "ignore")

        result_html = GetUrlSrc(as_url, u"cp949")

        #wx.MessageBox(result_html, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        result_text = re.findall(script_pattern, result_html, re.DOTALL)

        result_title = re.findall(title_pattern, result_html, re.DOTALL)

        print result_title

        if result_text:

            #wx.MessageBox(result_text[0], u"Test", wx.OK|wx.ICON_INFORMATION, self)

            #ls_return = " ".join(str(re.sub("<[^>]*>".decode("utf-8", "ignore"), "".decode("utf-8", "ignore"), result_text[0]).encode("cp949", "ignore")).split())

            #wx.MessageBox(result_text[0], u"News", wx.OK|wx.ICON_INFORMATION)

            return ls_temp_header + u"""<title>""" + result_title[0] + u"""</title>""" + result_text[0] + ls_temp_footer

    elif as_site == u"TITLE":

        html_src_uni = GetUrlSrc(as_url, 'utf-8')

        soup = BeautifulSoup(html_src_uni)

        ls_temp = str(soup('title')).decode('utf-8', 'ignore')

        pattern = u'<title>(.*?)</title>'

        ls_result_title = re.findall(pattern, ls_temp, re.DOTALL)

        ls_temp = str(soup('link')).decode('utf-8', 'ignore')

        pattern = u'<link>(.*?)</link>'

        ls_result_link = re.findall(pattern, ls_temp, re.DOTALL)

        ls_temp = str(soup('description')).decode('utf-8', 'ignore')

        ls_temp = ls_temp.replace(u'신문기사</description>', u'신문기사..&lt;img')

        pattern = u'<description>(.*?)..&lt;img'

        ls_result_description = re.findall(pattern, ls_temp, re.DOTALL)

        

        ls_temp_body_header = u"""<title>""" + ls_result_title[0] + u"""</title>""" + u"""<table width="1010" height="25" border="0" cellpadding="0" cellspacing="0"><tr><td width="1000" height="10" class="news">"""

        ls_temp_body_footer = u"""</a></td></tr></table>"""

        ls_temp_body = u""

        for ll_idx in range(len(ls_result_title)):

            if ll_idx == 0:

                continue

            ls_temp_body = ls_temp_body + ls_temp_body_header + str(ll_idx) + u" : " + u"""<a href=" """ + ls_result_link[ll_idx] + u""" ">""" + ls_result_title[ll_idx] + ls_temp_body_footer

        

        if return_val == None:

            return ls_temp_header + ls_temp_body + ls_temp_footer

        else:

            return_val[return_idx] = ls_temp_header + ls_temp_body + ls_temp_footer

            threadexit()


def threadexit():

    global threadsleft

    lock.acquire()

    threadsleft -= 1

    lock.release()


def main():

    

    global news_rss, threadsleft, lock, news_hosts

    news_rss = [u""]

    lock = thread.allocate_lock()


    news_hosts = [u"http://mk.co.kr.feedsportal.com/c/34147/f/618372/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618373/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618374/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618375/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618376/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618377/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618378/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618379/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618381/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/651700/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/651701/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618383/index.rss",

                  u"http://mk.co.kr.feedsportal.com/c/34147/f/618384/index.rss"]


    start = time.time()

    

    threadsleft = len(news_hosts)

    print len(news_hosts)

    

    for i in range(len(news_hosts)):

        news_rss.append(u"")

        thread.start_new_thread(SetPage, (news_hosts[i], u"TITLE", news_rss, i ))

        

    while threadsleft:

        pass


    print time.time() - start

    

    app = wx.App()

    frm = wx.Frame(None, style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.FRAME_EX_METAL, title=u"MK_RSS Reader v0.9", size=(1048,768))

    frm.CreateStatusBar()

    ico = wx.Icon(u"MK_RSS.ico", wx.BITMAP_TYPE_ICO)

    frm.SetIcon(ico)

    pnl = TestPanel(frm)

    frm.Show()

    frm.Center()

    app.MainLoop()


#----------------------------------------------------------------------

if __name__ == '__main__':

    main()


2013.10.07

#!/usr/bin/env python

#-*- coding:utf-8 -*-


import wx

import wx.html2

import urllib2

import re


news_url = u""


#----------------------------------------------------------------------

class TestPanel(wx.Panel):

    

    

    def __init__(self, parent):

        

        

        wx.Panel.__init__(self, parent)


        self.current = u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss"

        self.frame = self.GetTopLevelParent()

        self.titleBase = self.frame.GetTitle()


        sizer = wx.BoxSizer(wx.VERTICAL)

        

        grpSizer = wx.BoxSizer(wx.HORIZONTAL)

        

        st1 = wx.StaticText(self, label='News Category : ')

        grpSizer.Add(st1, 0, wx.CENTER|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"경제", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoToEconomy, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"증권", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoToStock, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        btn = wx.Button(self, -1, u"부동산", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnGoToRealEState, btn)

        grpSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        

        sizer.Add(grpSizer, 0, wx.EXPAND)

        

        sizer.Add((-1, 10))

        

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)


        #btn = wx.Button(self, -1, u"Open", style=wx.BU_EXACTFIT)

        #self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)

        #btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        btn = wx.Button(self, -1, u"<--", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)


        btn = wx.Button(self, -1, u"-->", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)


        btn = wx.Button(self, -1, u"Stop", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        btn = wx.Button(self, -1, u"Refresh", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        txt = wx.StaticText(self, -1, u"Location:")

        btnSizer.Add(txt, 0, wx.CENTER|wx.ALL, 2)


        self.location = wx.ComboBox(

            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)

        self.location.AppendItems([u"http://file.mk.co.kr/news/rss/rss_50300009.xml",

                                   u"http://news.mk.co.kr/rss/rss.php",

                                   u"http://www.mk.co.kr/"])


        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)

        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)

        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)


        sizer.Add(btnSizer, 0, wx.EXPAND)

        

        sizer.Add((-1, 10))

        

        self.wv = wx.html2.WebView.New(self)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.OnWebViewNavigated, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)

        sizer.Add(self.wv, 1, wx.EXPAND)

        

        self.SetSizer(sizer)


        self.wv.LoadURL(self.current)


    # WebView events

    def OnWebViewNavigating(self, evt):

        # this event happens prior to trying to get a resource

        print u"OnWebViewNavigating URL is : %s" % evt.GetURL()

        #wx.MessageBox(evt.GetURL(), u"Target URL is...", wx.OK|wx.ICON_INFORMATION, self)

        # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

        if (u"http://mk.co.kr.feedsportal.com/c/" in evt.GetURL()) and (not u"/index.rss" in evt.GetURL()):

            news_url = evt.GetURL()

            news_script = SetPage(evt.GetURL(), u"MK")

            self.wv.SetPage(u"<html><div>" + news_script + u"</div></html>", news_url)

            evt.Veto()

            self.current = news_url

            self.location.SetString(0, self.current)


    def OnWebViewNavigated(self, evt):

        self.frame.SetStatusText(u"Loading %s..." % evt.GetURL())


    def OnTestButton(self, evt):

        pass


    def OnWebViewLoaded(self, evt):

        # The full document has loaded

        self.current = evt.GetURL()

        if self.current == u"http:///":

            self.current = self.location.GetString(0)

            self.location.SetValue(self.location.GetString(0))

        else:

            self.location.SetValue(self.current)

        self.frame.SetStatusText(u"Loaded")

        #self.wv.RunScript("""alert('""" + self.current + """');""")

        #self.wv.RunScript("""

        #//call logIn();

        #//document.getElementsByName('q')[0].value="hist";

        #//document.getElementById('openididentifier').value="ident";

        #""")

        #self.wv.SetPage(self, """<html>하하하</html>""", """http://www.naver.com""")



    def OnWebViewTitleChanged(self, evt):

        # Set the frame's title to include the document's title

        self.frame.SetTitle("%s -- %s" % (self.titleBase, evt.GetString()))


    # Control bar events

    def OnLocationSelect(self, evt):

        url = self.location.GetStringSelection()

        print(u"OnLocationSelect: %s\n" % url)

        self.wv.LoadURL(url)


    def OnLocationEnter(self, evt):

        url = self.location.GetValue()

        self.location.Append(url)

        self.wv.LoadURL(url)


    def OnOpenButton(self, event):

        dlg = wx.TextEntryDialog(self, u"Input Url or local file path", u"URL", self.current, wx.OK|wx.CANCEL)

        dlg.CentreOnParent()


        if dlg.ShowModal() == wx.ID_OK:

            self.current = dlg.GetValue()

            self.wv.LoadURL(self.current)


        dlg.Destroy()


    def OnPrevPageButton(self, event):

        for i in self.wv.GetBackwardHistory():

            print i.Url, i.Title

        self.wv.GoBack()

        #self.wv.LoadURL(u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss")


    def OnNextPageButton(self, event):

        for i in self.wv.GetForwardHistory():

            print i.URL, i.Title

        self.wv.GoForward()


    def OnCheckCanGoBack(self, event):

        event.Enable(self.wv.CanGoBack())


    def OnCheckCanGoForward(self, event):

        event.Enable(self.wv.CanGoForward())


    def OnStopButton(self, evt):

        self.wv.Stop()


    def OnRefreshPageButton(self, evt):

        self.wv.Reload()

        

    def OnGoToEconomy(self, evt):

        self.current = u"http://mk.co.kr.feedsportal.com/c/34147/f/618374/index.rss"

        self.wv.LoadURL(self.current)

        

    def OnGoToStock(self, evt):

        self.current = u"http://mk.co.kr.feedsportal.com/c/34147/f/618379/index.rss"

        self.wv.LoadURL(self.current)

        

    def OnGoToRealEState(self, evt):

        self.current = u"http://mk.co.kr.feedsportal.com/c/34147/f/618380/index.rss"

        self.wv.LoadURL(self.current)



#----------------------------------------------------------------------

def GetUrlSrc(as_url, as_decoding):

    html_src = urllib2.urlopen(as_url).read()

    return html_src.decode(as_decoding, 'ignore')


def SetPage(as_url, as_site):

    # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

    if as_site == u"MK":

        script_pattern = "<div\sclass=\'read_txt\'>(.*?)\s*?<!--이미지".decode("utf-8", "ignore")

        result_html = GetUrlSrc(as_url, u"cp949")

        #wx.MessageBox(result_html, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        result_text = re.findall(script_pattern, result_html, re.DOTALL)

        if result_text:

            #wx.MessageBox(result_text[0], u"Test", wx.OK|wx.ICON_INFORMATION, self)

            #ls_return = " ".join(str(re.sub("<[^>]*>".decode("utf-8", "ignore"), "".decode("utf-8", "ignore"), result_text[0]).encode("cp949", "ignore")).split())

            #wx.MessageBox(result_text[0], u"News", wx.OK|wx.ICON_INFORMATION)

            return result_text[0]


def main():

    app = wx.App()

    frm = wx.Frame(None, style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.FRAME_EX_METAL, title=u"MK_RSS Reader v0.9", size=(1048,768))

    frm.CreateStatusBar()

    pnl = TestPanel(frm)

    frm.Show()

    frm.Center()

    app.MainLoop()


#----------------------------------------------------------------------

if __name__ == '__main__':

    main()


2013.10.06

#!/usr/bin/env python

#-*- coding:utf-8 -*-


import wx

import wx.html2

import urllib2

import re


#----------------------------------------------------------------------

class TestPanel(wx.Panel):

    def __init__(self, parent):

        wx.Panel.__init__(self, parent)


        self.current = u"http://file.mk.co.kr/news/rss/rss_50300009.xml"

        self.frame = self.GetTopLevelParent()

        self.titleBase = self.frame.GetTitle()


        sizer = wx.BoxSizer(wx.VERTICAL)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)


        self.wv = wx.html2.WebView.New(self)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.OnWebViewNavigated, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)


        btn = wx.Button(self, -1, "Open", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        btn = wx.Button(self, -1, "<--", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)


        btn = wx.Button(self, -1, "-->", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)


        btn = wx.Button(self, -1, "Stop", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        btn = wx.Button(self, -1, "Refresh", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        txt = wx.StaticText(self, -1, "Location:")

        btnSizer.Add(txt, 0, wx.CENTER|wx.ALL, 2)


        self.location = wx.ComboBox(

            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)

        self.location.AppendItems(['http://wxPython.org',

                                   'http://wxwidgets.org',

                                   'http://google.com'])


        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)

        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)

        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)


        sizer.Add(btnSizer, 0, wx.EXPAND)

        sizer.Add(self.wv, 1, wx.EXPAND)

        self.SetSizer(sizer)


        self.wv.LoadURL(self.current)


    # WebView events

    def OnWebViewNavigating(self, evt):

        # this event happens prior to trying to get a resource

        print u"Target URL is : %s" % evt.GetURL()

        #wx.MessageBox(evt.GetURL(), u"Target URL is...", wx.OK|wx.ICON_INFORMATION, self)

        # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

        if u"http://mk.co.kr.feedsportal.com/c/" in evt.GetURL():

            news_script = SetPage(evt.GetURL(), u"MK")

            print type(news_script)

            self.wv.SetPage(u"<html><div>" + news_script + u"</div></html>", "")

            evt.Veto()


    def OnWebViewNavigated(self, evt):

        self.frame.SetStatusText("Loading %s..." % evt.GetURL())


    def OnTestButton(self, evt):

        pass


    def OnWebViewLoaded(self, evt):

        # The full document has loaded

        self.current = evt.GetURL()

        self.location.SetValue(self.current)

        self.frame.SetStatusText("Loaded")

        #self.wv.RunScript("""alert('""" + self.current + """');""")

        #self.wv.RunScript("""

        #//call logIn();

        #//document.getElementsByName('q')[0].value="hist";

        #//document.getElementById('openididentifier').value="ident";

        #""")

        #self.wv.SetPage(self, """<html>하하하</html>""", """http://www.naver.com""")



    def OnWebViewTitleChanged(self, evt):

        # Set the frame's title to include the document's title

        self.frame.SetTitle("%s -- %s" % (self.titleBase, evt.GetString()))


    # Control bar events

    def OnLocationSelect(self, evt):

        url = self.location.GetStringSelection()

        print('OnLocationSelect: %s\n' % url)

        self.wv.LoadURL(url)


    def OnLocationEnter(self, evt):

        url = self.location.GetValue()

        self.location.Append(url)

        self.wv.LoadURL(url)


    def OnOpenButton(self, event):

        dlg = wx.TextEntryDialog(self, "Open Location",

                                "Enter a full URL or local path",

                                self.current, wx.OK|wx.CANCEL)

        dlg.CentreOnParent()


        if dlg.ShowModal() == wx.ID_OK:

            self.current = dlg.GetValue()

            self.wv.LoadURL(self.current)


        dlg.Destroy()


    def OnPrevPageButton(self, event):

        #for i in self.wv.GetBackwardHistory():

        #    print i.Url, i.Title

        #self.wv.GoBack()

        self.wv.LoadURL(u"http://file.mk.co.kr/news/rss/rss_50300009.xml")


    def OnNextPageButton(self, event):

        #for i in self.wv.GetForwardHistory():

        #    print i.URL, i.Title

        self.wv.GoForward()


    def OnCheckCanGoBack(self, event):

        event.Enable(self.wv.CanGoBack())


    def OnCheckCanGoForward(self, event):

        event.Enable(self.wv.CanGoForward())


    def OnStopButton(self, evt):

        self.wv.Stop()


    def OnRefreshPageButton(self, evt):

        self.wv.Reload()



#----------------------------------------------------------------------

def GetUrlSrc(as_url, as_decoding):

    html_src = urllib2.urlopen(as_url).read()

    return html_src.decode(as_decoding, 'ignore')


def SetPage(as_url, as_site):

    # 1. URL이 기사 URL타입과 일치하면... 파싱 아니면 그냥 웹표시

    if as_site == u"MK":

        script_pattern = "<div\sclass=\'read_txt\'>(.*?)\s*?<!--이미지".decode("utf-8", "ignore")

        result_html = GetUrlSrc(as_url, u"cp949")

        #wx.MessageBox(result_html, u"Test", wx.OK|wx.ICON_INFORMATION, self)

        result_text = re.findall(script_pattern, result_html, re.DOTALL)

        if result_text:

            #wx.MessageBox(result_text[0], u"Test", wx.OK|wx.ICON_INFORMATION, self)

            #ls_return = " ".join(str(re.sub("<[^>]*>".decode("utf-8", "ignore"), "".decode("utf-8", "ignore"), result_text[0]).encode("cp949", "ignore")).split())

            #wx.MessageBox(result_text[0], u"News", wx.OK|wx.ICON_INFORMATION)

            return result_text[0]


def main():

    app = wx.App()

    frm = wx.Frame(None, style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.FRAME_EX_METAL, title=u"MK_RSS Reader v0.9", size=(1048,768))

    frm.CreateStatusBar()

    pnl = TestPanel(frm)

    frm.Show()

    frm.Center()

    app.MainLoop()


#----------------------------------------------------------------------

if __name__ == '__main__':

    main()


'Study > python' 카테고리의 다른 글

[연습]AutoPOKO ~~  (0) 2013.11.11
[펌]python thread 사용예  (0) 2013.10.16
wxpython webview test  (0) 2013.10.05
[연습중]MK RSS 파싱  (0) 2013.09.23
[연습]손바닥삼국지 오토  (0) 2013.09.22
Posted by 땡보
2013. 10. 5. 09:39


#!/usr/bin/env python

#-*- coding:utf-8 -*-


import wx

import wx.html2


#----------------------------------------------------------------------


class TestPanel(wx.Panel):

    def __init__(self, parent):

        wx.Panel.__init__(self, parent)


        self.current = "http://www.google.com"

        self.frame = self.GetTopLevelParent()

        self.titleBase = self.frame.GetTitle()


        sizer = wx.BoxSizer(wx.VERTICAL)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.wv = wx.html2.WebView.New(self)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.OnWebViewNavigated, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)

        self.Bind(wx.html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)


        btn = wx.Button(self, -1, "Open", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        btn = wx.Button(self, -1, "<--", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)


        btn = wx.Button(self, -1, "-->", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)


        btn = wx.Button(self, -1, "Stop", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        btn = wx.Button(self, -1, "Refresh", style=wx.BU_EXACTFIT)

        self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)

        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)


        txt = wx.StaticText(self, -1, "Location:")

        btnSizer.Add(txt, 0, wx.CENTER|wx.ALL, 2)


        self.location = wx.ComboBox(

            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)

        self.location.AppendItems(['http://wxPython.org',

                                   'http://wxwidgets.org',

                                   'http://google.com'])


        #for url in ['http://wxPython.org',

        #            'http://wxwidgets.org',

        #            'http://google.com']:

        #    item = webview.WebViewHistoryItem(url, url)

        #    self.wv.LoadHistoryItem(item)


        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)

        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)

        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)



        sizer.Add(btnSizer, 0, wx.EXPAND)

        sizer.Add(self.wv, 1, wx.EXPAND)

        self.SetSizer(sizer)


        self.wv.LoadURL(self.current)




    # WebView events

    def OnWebViewNavigating(self, evt):

        # this event happens prior to trying to get a resource

        if evt.GetURL() == 'http://www.microsoft.com/':

            if wx.MessageBox("Are you sure you want to visit Microsoft?",

                             style=wx.YES_NO|wx.ICON_QUESTION) == wx.NO:

                # This is how you can cancel loading a page.

                evt.Veto()



    def OnWebViewNavigated(self, evt):

        self.frame.SetStatusText("Loading %s..." % evt.GetURL())



    def OnWebViewLoaded(self, evt):

        # The full document has loaded

        if u'about:blank' in evt.GetURL():

            return -1

        self.current = evt.GetURL()

        self.location.SetValue(self.current)

        self.frame.SetStatusText("Loaded")

        self.wv.RunScript("""

        document.getElementsByName('q')[0].value="hist";

        //document.getElementById('openididentifier').value="ident";

        //document.getElementsByName('login')[1].click()

        """)



    def OnWebViewTitleChanged(self, evt):

        # Set the frame's title to include the document's title

        self.frame.SetTitle("%s -- %s" % (self.titleBase, evt.GetString()))



    # Control bar events

    def OnLocationSelect(self, evt):

        url = self.location.GetStringSelection()

        print('OnLocationSelect: %s\n' % url)

        self.wv.LoadURL(url)


    def OnLocationEnter(self, evt):

        url = self.location.GetValue()

        self.location.Append(url)

        self.wv.LoadURL(url)



    def OnOpenButton(self, event):

        dlg = wx.TextEntryDialog(self, "Open Location",

                                "Enter a full URL or local path",

                                self.current, wx.OK|wx.CANCEL)

        dlg.CentreOnParent()


        if dlg.ShowModal() == wx.ID_OK:

            self.current = dlg.GetValue()

            self.wv.LoadURL(self.current)


        dlg.Destroy()


    def OnPrevPageButton(self, event):

        for i in self.wv.GetBackwardHistory():

            print i.Url, i.Title

        self.wv.GoBack()


    def OnNextPageButton(self, event):

        for i in self.wv.GetForwardHistory():

            print i.URL, i.Title

        self.wv.GoForward()


    def OnCheckCanGoBack(self, event):

        event.Enable(self.wv.CanGoBack())


    def OnCheckCanGoForward(self, event):

        event.Enable(self.wv.CanGoForward())


    def OnStopButton(self, evt):

        self.wv.Stop()


    def OnRefreshPageButton(self, evt):

        self.wv.Reload()



#----------------------------------------------------------------------



def main():

    app = wx.App()

    frm = wx.Frame(None, style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.FRAME_EX_METAL, title="html2.WebView sample", size=(700,500))

    frm.CreateStatusBar()

    pnl = TestPanel(frm)

    frm.Show()

    app.MainLoop()



#----------------------------------------------------------------------


if __name__ == '__main__':

    main()


'Study > python' 카테고리의 다른 글

[펌]python thread 사용예  (0) 2013.10.16
[연습]wxpython rss reader  (0) 2013.10.06
[연습중]MK RSS 파싱  (0) 2013.09.23
[연습]손바닥삼국지 오토  (0) 2013.09.22
[연습]Python regular expression & sqlite  (0) 2013.09.22
Posted by 땡보
2013. 9. 23. 06:42

'Study > python' 카테고리의 다른 글

[연습]wxpython rss reader  (0) 2013.10.06
wxpython webview test  (0) 2013.10.05
[연습]손바닥삼국지 오토  (0) 2013.09.22
[연습]Python regular expression & sqlite  (0) 2013.09.22
[펌]Unicode In Python, Completely Demystified  (0) 2013.09.18
Posted by 땡보
2013. 9. 22. 15:53

본 소스 코드는 개인 학습용으로 연습삼아 작성한 코드 입니다.

또한 2012년 작성 코드로 현재 동작 여부는 알 수 없습니다.

혹시나 퍼가셔서 사용하시거나, 또는 수정하여 사용하시다 발생하는 모든 책임은 사용자 본인에게 있음을 알려드립니다.

#!/usr/bin/env python

#-*- coding:ms949 -*-


'''

    목  적 : Python 정규식 및 urllib 연습

    버  전 : Python 3.2

    연습일 : 2012.04.16

    동  작 :

    모바일 게임 어플인 '손바닥삼국지'를 자동으로 플레이 해준다.

'''

import time

import http.client

import urllib.parse

import re

import random

import sys

import os

import copy


base_user_id   = ''

base_user_pw   = ''

base_user_host = 'k5.tapsg.com'

base_cookie    = ''

base_token     = ''

base_city_id   = ''

city_id_all    = ''

base_max_cnt   = 500                    #오랑캐 최대 검색 좌표수(섭 트레픽 증가로 인한 계정 블럭을 방지)

base_find_cnt  = 100

base_find_type = 3                      #찾고 싶은 오랑캐 타입(별!!! 카운트 내림차수 정렬임!!)


def chk_auth():

    get_auth_url =  '/auth.html'

    html_source = get_html_response(get_auth_url, 3)

    if html_source == '::ERROR::':

        sys.exit()

    if '"code":0' in html_source:

        #print('실행 장소 인증 성공')

        return

    else:

        print('허가되지 않은 장소에서의실행 요청입니다!!')

        sys.exit()


def auto_attack(city_id, inteval_sec, type_orang, type_soldier, num_soldier):

    next_ip             = 'next'

    err_cnt             = 0

    food_per_attack     = 0

    interval_per_attack = 0

    city_tot_money      = 0

    city_tot_food       = 0

    need_chg_tot_gold   = 0


    while True:

        # 도시정보 호출 후 식량자원량 추출

        city_resource = get_city_resource(city_id)

        if city_resource:

            if city_resource == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[01]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            else:

                city_tot_money = city_resource[0][0]

                city_tot_food  = city_resource[0][1]

                next_ip = 'next'

                rand_timesleep()                

        else:

            if err_cnt <= 3:

                err_cnt += 1

                print('[02]Error발생')

                timesleep(5)

                continue

            else:

                print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                return -1

        

        if next_ip == 'next':

            # 1. 목록(의미없음)

            # GET /game/api_fav.php?jsonpcallback=jsonp1334359483814&_=1334372334923&key=ac91d18916be985c476e6a4bbfb7bd56&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334423944539({"code":0,"ret":{"friend":[{"id":6800,"nick":"harddisk","nationid":2,"level":57,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":19762,"nick":"shoowhip","nationid":2,"level":37,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":19788,"nick":"\uac81\ud608\uc774","nationid":1,"level":50,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":19794,"nick":"chakani710","nationid":3,"level":47,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":20424,"nick":"sphere604","nationid":1,"level":47,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]},{"id":20834,"nick":"\uad00\uc6b0\uc6b4\uc7a5","nationid":1,"level":20,"guild":"\uc2ed\uc790\uad70","guildid":58,"gpower":5,"gflag":68,"protection":0,"status":0,"conq":[0,0,null]},{"id":21006,"nick":"abcd1004","nationid":1,"level":12,"guild":"","guildid":0,"gpower":0,"gflag":1,"protection":0,"status":0,"conq":[0,0,null]},{"id":21045,"nick":"\uac00\ub294\ube44\uc628\ub2e4","nationid":2,"level":34,"guild":"","guildid":0,"gpower":0,"gflag":1,"protection":0,"status":0,"conq":[0,0,null]},{"id":21080,"nick":"\uc815\uc624","nationid":1,"level":25,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"status":0,"conq":[0,0,null]}]}})

            get_list_url = '/game/api_fav.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_list_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[03]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            # 에러만 아니면 성공여부 상관없음!!

            next_ip = 'next'

            rand_timesleep()


        if next_ip == 'next':

            # 2. 친추 오랑캐 리스트 (좌표, 공격 횟수, 별수 추출) 

            # GET /game/api_fav.php?jsonpcallback=jsonp1334359483815&_=1334372336989&key=ac91d18916be985c476e6a4bbfb7bd56&act=getfavnpc&cat=2&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334423982684({"code":0,"ret":{"favs":[[182038,258,27,1,0],[182039,253,26,1,0],[182040,239,19,1,0],[182041,121,17,1,0],[182042,46,21,1,0],[182044,248,9,1,0],[182045,67,11,1,0],[182046,41,13,1,0],[182400,164,95,1,0],[182401,146,87,1,0],[182402,147,77,1,0],[182403,206,83,1,0],[182404,159,68,1,0],[182405,159,67,1,0],[182406,193,68,1,0],[182407,176,69,1,2],[182408,138,55,1,0],[182409,135,47,1,0],[182410,206,39,1,0],[182411,152,32,1,0],[184781,173,44,1,0],[184782,206,44,1,0],[184783,279,47,1,0],[184784,180,42,1,0],[184786,268,37,1,0],[184787,257,40,1,0],[184788,211,30,1,0],[184789,194,35,1,0],[184790,238,33,1,0],[184791,170,27,1,0],[184792,167,25,1,0],[184795,265,27,1,0],[184796,257,22,1,0],[184797,166,5,1,0],[186088,164,115,1,0],[186089,62,119,1,0],[186090,57,119,1,0],[186091,4,124,1,0],[186092,114,116,1,1],[186093,104,111,1,0],[186094,91,112,1,0],[186095,221,106,1,0],[186096,219,105,1,0],[186097,265,109,1,0],[186098,191,110,1,0],[186099,234,108,1,0],[186100,227,106,1,0],[186101,78,104,1,1],[186102,65,110,1,0],[186103,27,106,1,0],[186104,199,101,1,0],[186105,276,100,1,0],[186106,272,101,1,0],[186107,256,102,1,0],[186108,251,97,1,0],[186109,102,102,1,0],[187815,152,203,1,0],[187816,131,200,1,0],[187817,27,209,1,0],[187818,163,201,1,0],[187819,213,198,1,0],[187820,117,198,1,0],[187821,109,201,1,0],[187822,34,199,1,0],[187823,19,203,1,0],[187824,136,196,1,0],[187825,198,196,1,0],[187826,181,191,1,0],[187827,172,195,1,0],[187828,243,196,1,0],[187829,166,195,1,0],[187830,220,192,1,0],[187831,261,194,1,0],[187832,197,190,1,0],[187833,143,187,1,0],[187834,91,195,1,0],[187835,73,196,1,0],[187836,181,183,1,0],[187837,198,186,1,0],[187838,43,193,1,0],[187839,39,190,1,0],[187840,277,188,1,0],[187841,120,189,1,0],[187842,64,187,1,0],[187843,68,186,1,0],[187844,163,181,1,0],[187845,165,180,1,0],[187846,10,187,1,0],[187847,212,179,1,0],[187848,139,176,1,0],[187849,212,178,1,0],[187850,194,180,1,0],[187851,233,177,1,0],[187852,122,180,1,0],[187853,110,182,1,0],[187854,86,179,1,0],[187855,85,177,1,0],[187856,34,177,1,0],[187857,161,175,1,0],[187858,212,174,1,0],[187859,20,177,1,0],[187860,17,176,1,0],[187861,13,177,1,0],[187862,188,170,1,0],[187863,257,173,1,0],[187864,251,171,1,0],[187866,166,79,1,0],[187867,193,61,1,0],[187868,250,38,1,0],[187871,264,135,4,0],[181998,137,31,1,3],[181999,126,30,1,3],[182000,147,28,1,3],[182001,120,34,1,3],[182036,246,26,1,3],[182037,59,31,1,3],[182043,276,10,1,3],[182047,275,1,1,3],[184785,178,40,1,3],[184793,268,30,1,3]]}})

            # [182038,258,27,1,0] ==> [오랑캐ID, X좌표, Y좌표, 별, 공격횟수]

            # 만약 findall 리스트 item수가 0이면 루프 탈출 후 return interval

            get_orang_xy_url = '/game/api_fav.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&act=getfavnpc&cat=2&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_orang_xy_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[04]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                find_orang_xy = re.findall('\[\d+,(\d+),(\d+),' + str(type_orang) + ',[0-2]', html_source)

                if find_orang_xy:

                    attack_x = find_orang_xy[0][0]

                    attack_y = find_orang_xy[0][1]

                    print('공격좌표 추출 완료 : ' + attack_x + '/' + attack_y)

                    next_ip = 'next'

                    rand_timesleep()

                else:

                    print('더이상 공격할 좌표가 없어 자동사냥 작업을 종료 합니다.')

                    next_ip = 'exit_auto_attack'

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[05]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

        

        if next_ip == 'next':

            # 3. 공격좌표 이상유무 파악!!

            # GET /game/armament_action_do_api.php?jsonpcallback=jsonp1334359483816&_=1334372353885&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&act=anum&x=78&y=104&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424047624({"code":0,"ret":0})

            # "code":0,"ret":0 응답이 이거면 진행 아니면 다음루프 continue

            is_target_ok_url = '/game/armament_action_do_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&act=anum&x=' + attack_x + '&y=' + attack_y + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            #print('is_target_ok_url :' + is_target_ok_url)

            html_source = get_html_response(is_target_ok_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[06]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                next_ip = 'next'

                print('좌표[' + attack_x + '/' + attack_y + '] 공격가능!!')

                rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[08]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':

            # 4. 병력 정보

            # GET /game/soldier_educate_api.php?jsonpcallback=jsonp1334359483817&_=1334372353891&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424148283({"code":0,"ret":{"soldiers":[[1,0,1],[2,110,1],[3,0,1],[4,0,1],[5,0,1],[6,0,1],[7,0,1],[8,0,1],[9,0,0],[10,0,1],[11,500,1],[12,0,0],[13,0,1],[14,0,0],[15,4500,1]],"space":5390,"head":7103,"def":1,"next":[16,22],"f":107896}})

            # type_soldier가 num_soldier만큼 있으면 통과 없으면 5, 6, 7, 8 스킵후 interval 만큼 대기!! type_soldier, num_soldier

            get_soldier_num_url = '/game/soldier_educate_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_soldier_num_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[09]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                find_soldier_num = re.findall('\['+ str(type_soldier) + ',(\d+),[01]\]', html_source)

                if find_soldier_num:

                    my_soldier_num = find_soldier_num[0]

                    

                    if int(my_soldier_num) >= int(num_soldier):

                        # 병력이 충분하면.. 통과

                        print('병력 보유[' + str(my_soldier_num) + '] 공격 진행!!')

                        next_ip = 'next'

                        rand_timesleep()

                    else:

                        # 병력이 적으면!! 인터벌 대기

                        print('더이상 공격할 병력이 없어 다음 인터벌 까지 대기합니다.')

                        next_ip = 'wait_interval'

                        rand_timesleep()

                else:

                    print('더이상 공격할 병력이 없어 다음 인터벌 까지 대기합니다.')

                    next_ip = 'wait_interval'

                    rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[10]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

        

        if next_ip == 'next':

            # 5. 통솔 장수 선택

            # GET /game/gen_conscribe_api.php?jsonpcallback=jsonp1334359483818&_=1334372360888&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&action=gen_list&extra=1&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424202909({"code":0,"ret":{"hero":[{"id":89862,"gid":189,"p":33,"i":41,"c1":18,"f":80,"g":13,"c2":900,"fy":0,"s":0,"e":16,"w":1,"tw":8,"tl":31,"ex":118887,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":250,"ns":0,"ncd":0,"pr":39000},{"id":93364,"gid":179,"p":30,"i":55,"c1":16,"f":75,"g":13,"c2":823,"fy":0,"s":0,"e":16,"w":0,"tw":8,"tl":17,"ex":10843,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":96018,"gid":207,"p":59,"i":12,"c1":33,"f":75,"g":13,"c2":830,"fy":0,"s":0,"e":16,"w":1,"tw":7,"tl":26,"ex":291604,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":97215,"gid":177,"p":31,"i":49,"c1":29,"f":73,"g":13,"c2":845,"fy":0,"s":0,"e":16,"w":0,"tw":7,"tl":29,"ex":31237,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":97340,"gid":186,"p":32,"i":43,"c1":19,"f":75,"g":13,"c2":844,"fy":0,"s":0,"e":16,"w":1,"tw":2,"tl":23,"ex":3042,"te":565620,"np":8,"ni":15,"nc1":11,"nc2":419,"ns":0,"ncd":0,"pr":39000},{"id":98342,"gid":126,"p":33,"i":53,"c1":26,"f":30,"g":12,"c2":879,"fy":0,"s":0,"e":16,"w":0,"tw":18,"tl":27,"ex":221902,"te":257100,"np":15,"ni":45,"nc1":19,"nc2":759,"ns":0,"ncd":0,"pr":36000},{"id":104287,"gid":185,"p":11,"i":42,"c1":13,"f":60,"g":12,"c2":617,"fy":0,"s":0,"e":16,"w":0,"tw":0,"tl":3,"ex":99753,"te":257100,"np":0,"ni":0,"nc1":0,"nc2":0,"ns":0,"ncd":0,"pr":36000},{"id":109341,"gid":73,"p":44,"i":54,"c1":32,"f":15,"g":15,"c2":830,"fy":0,"s":0,"e":16,"w":2,"tw":2,"tl":10,"ex":241832,"te":2737601,"np":0,"ni":0,"nc1":0,"nc2":30,"ns":0,"ncd":0,"pr":45000},{"id":111918,"gid":45,"p":37,"i":54,"c1":26,"f":55,"g":10,"c2":854,"fy":0,"s":0,"e":16,"w":0,"tw":0,"tl":0,"ex":26823,"te":53119,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":30000}]}})

            # jsonp1334705981745({"code":0,"ret":{"hero":[{"id":89862,"gid":189,"p":33,"i":41,"c1":18,"f":85,"g":13,"c2":910,"fy":0,"s":0,"e":16,"w":0,"tw":10,"tl":32,"ex":443066,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":260,"ns":0,"ncd":0,"pr":39000},{"id":93364,"gid":179,"p":30,"i":55,"c1":16,"f":75,"g":13,"c2":823,"fy":0,"s":0,"e":16,"w":1,"tw":9,"tl":17,"ex":332048,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":96018,"gid":207,"p":62,"i":12,"c1":33,"f":75,"g":14,"c2":868,"fy":0,"s":0,"e":16,"w":1,"tw":7,"tl":26,"ex":47550,"te":1244364,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":42000},{"id":97215,"gid":177,"p":31,"i":49,"c1":29,"f":73,"g":13,"c2":845,"fy":0,"s":0,"e":16,"w":0,"tw":8,"tl":31,"ex":352312,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":180,"ns":0,"ncd":0,"pr":39000},{"id":97340,"gid":186,"p":32,"i":43,"c1":19,"f":75,"g":13,"c2":844,"fy":0,"s":0,"e":16,"w":2,"tw":3,"tl":23,"ex":323906,"te":565620,"np":8,"ni":15,"nc1":11,"nc2":419,"ns":0,"ncd":0,"pr":39000},{"id":98342,"gid":126,"p":33,"i":57,"c1":26,"f":35,"g":13,"c2":917,"fy":0,"s":0,"e":16,"w":4,"tw":22,"tl":27,"ex":284646,"te":565620,"np":15,"ni":45,"nc1":19,"nc2":759,"ns":0,"ncd":0,"pr":39000},{"id":104287,"gid":185,"p":11,"i":45,"c1":13,"f":60,"g":13,"c2":653,"fy":0,"s":0,"e":16,"w":0,"tw":0,"tl":4,"ex":162018,"te":565620,"np":0,"ni":0,"nc1":0,"nc2":0,"ns":0,"ncd":0,"pr":39000},{"id":109341,"gid":73,"p":44,"i":54,"c1":32,"f":20,"g":15,"c2":950,"fy":0,"s":0,"e":16,"w":0,"tw":2,"tl":12,"ex":561262,"te":2737601,"np":0,"ni":0,"nc1":0,"nc2":150,"ns":0,"ncd":0,"pr":45000}]}})

            # 만약 findall 리스트 item수가 0이면 10번으로

            # 리스트 item은 있으나 c2(통솔력)가 딸리는 장수들 뿐이면 역시 10번으로

            # 리스트item은 있으나  e(기력)이 딸리는 장수들 뿐이면 역시 10번으로

            

            get_gen_id_url = '/game/gen_conscribe_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&action=gen_list&extra=1&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_gen_id_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[11]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                #find_gen_id = re.findall('"gid":(\d+),"p":\d+,"i":\d+,"c1":\d+,"f":\d+,"g":\d+,"c2":([' + str(num_soldier)[0] + '-9]\d*),', html_source)

                find_gen_id = re.findall('"gid":(\d+),"p":\d+,"i":\d+,"c1":\d+,"f":\d+,"g":\d+,"c2":(\d+),', html_source)

                selected_gen_id = ''

                if find_gen_id:

                    for loop_idx in find_gen_id:

                        if int(loop_idx[1]) >=  num_soldier:

                            selected_gen_id = loop_idx[0]

                            break

                        else:

                            selected_gen_id = ''

                    

                    if selected_gen_id != '':

                        print('통솔 장수 ID 추출 완료[' + str(selected_gen_id) + '] 공격 진행!!')

                        next_ip = 'next'

                        rand_timesleep()

                    else:

                        print('더이상 공격할 장수가 없어 다음 인터벌 까지 대기합니다.')

                        next_ip = 'wait_interval'

                        rand_timesleep()

                else:

                    print('더이상 공격할 장수가 없어 다음 인터벌 까지 대기합니다.')

                    next_ip = 'wait_interval'

                    rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[12]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':

            # 6. 공격정보 상세

            # GET /game/armament_action_do_api.php?jsonpcallback=jsonp1334359483819&_=1334372374733&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&action=do_war&attack_type=7&gen=189&area=78&area_x=104&soldier_num15=500&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424277458({"code":0,"ret":{"carry":396000,"cost_food":90000,"cost_wood":0,"cost_iron":0,"cost_gold":0,"distance":20160,"travel_sec":540}})

            # 음식소요와 공격명령 파라메터 생성!!

            # 타음 인터벌 맥스값 계산 세트!! 공식 : (travel_sec + 60 * 2)가  inteval_sec보다 크면 inteval_sec 교체

            attack_info_url = '/game/armament_action_do_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&action=do_war&attack_type=7&gen=' + selected_gen_id + '&area=' + attack_x + '&area_x=' + attack_y + '&soldier_num' + str(type_soldier) + '=' + str(num_soldier) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(attack_info_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[13]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                attack_info = re.search('"carry":(\d+),"cost_food":(\d+),"cost_wood":(\d+),"cost_iron":(\d+),"cost_gold":(\d+),"distance":(\d+),"travel_sec":(\d+)',html_source).group()

                attack_info = '&' + attack_info.replace('"', '').replace(':', '=').replace(',', '&')

                food_per_attack     = int(re.search('cost_food":(\d+),', html_source).group(1))

                interval_per_attack = int(re.search('travel_sec":(\d+)}', html_source).group(1)) * 2

                print('도시보유 식량 : ' + city_tot_food + ', 공격소요 식량 : ' + str(food_per_attack))

                print('공격소요시간(복귀시간포함) : ' + str(interval_per_attack))


                if int(city_tot_food) < int(food_per_attack):

                    # 식량교환(1골드당 7.6923 식량)

                    need_chg_tot_gold = int(food_per_attack / 7.6923)

                    # 계산된 골드 보다 10골드 더 교환 요건 걍 내맴

                    need_chg_tot_gold += 100

                    # 현재 도시의 돈이 need_chg_tot_gold보다 적으면 진행 불가 인터벌 대기!!

                    if city_tot_money < need_chg_tot_gold:

                        print('도시에 다음 전투 식량 교환을 위한 동전이 부족하여 다음 인터벌 까지 대기합니다.')

                        next_ip = 'wait_interval'

                        rand_timesleep()

                    else:

                        ret_do_g2f = do_g2f(need_chg_tot_gold, city_id)

                        if ret_do_g2f == '::ERROR::':

                            print('식량자원 교환에 실패하여 자동사냥을 중지합니다!!')

                            next_ip = 'exit_auto_attack'

                        else:

                            rand_timesleep()

                            print('식량자원 교환 성공!! 공격 진행!!')

                            next_ip = 'next'

                else:

                    next_ip = 'next'

                    print('식량자원 요건 충족!! 공격 진행!!')

                    rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[14]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':

            # 7. 도시자원 정보(의미 없음)

            # GET /game/get_cityinfo_api.php?jsonpcallback=jsonp1334359484911&_=1334372387271&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

            # jsonp1334424402425({"code":0,"ret":{"city":[27,183,764129,159000,1276893,159000,1214668,159000,1980380,159000,6656,8125,10,12,11,26,17,21,19,19,1,4,14,[{"id":52066,"itemid":166,"secs":502596},{"id":52201,"itemid":126,"secs":14202}],0],"grade":43,"money":100}})

            get_city_info_url = '/game/get_cityinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(get_city_info_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[15]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                next_ip = 'next'

                rand_timesleep()

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[16]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1


        if next_ip == 'next':        

            # 8. 공격명령!!

            # GET /game/armament_action_task_api.php?jsonpcallback=jsonp1334359483820&_=1334372411619&key=ac91d18916be985c476e6a4bbfb7bd56&city=23764&action=war_task&attack_type=7&gen=189&area=78&area_x=104&soldier_num15=500&_l=kr&_p=SG-IPHONE-KR&carry=396000&cost_food=90000&cost_wood=0&cost_iron=0&cost_gold=0&distance=7440&travel_sec=180 HTTP/1.1

            # jsonp1334424477066({"code":0,"ret":{"cd":[{"id":6334289,"cdtype":4,"target":7,"owner":189,"secs":540,"ret":0,"ext":"166\/79"}]}})

            do_attack_url = '/game/armament_action_task_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&action=war_task&attack_type=7&gen=' + selected_gen_id + '&area=' + attack_x + '&area_x=' + attack_y + '&soldier_num' + str(type_soldier) + '=' + str(num_soldier) + '&_l=kr&_p=SG-IPHONE-KR' + attack_info + '{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(do_attack_url, 2)

            if html_source == '::ERROR::':

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[15]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

            if '"code":0' in html_source:

                print('좌표[' + attack_x + '/' + attack_y + '] 공격완료!!')

                # 에러카운트 초기화

                err_cnt = 0

                # 롱텀 인터벌 판별 및 스왑

                if interval_per_attack > inteval_sec:

                    print('현재 인터벌[' + str(inteval_sec) + ']보다 큰 인터벌[' + str(interval_per_attack) + ']발견!! 스왑인터벌')

                    inteval_sec = interval_per_attack

                # 식량교환(1골드당 7.6923 식량)

                need_chg_tot_gold = int(food_per_attack / 7.6923)

                # 계산된 골드 보다 10골드 더 교환 요건 걍 내맴

                need_chg_tot_gold += 100

                

                # 현재 도시의 돈이 need_chg_tot_gold보다 적으면 진행 불가 인터벌 대기!!

                if int(city_tot_money) < int(need_chg_tot_gold):

                    print('도시에 다음 전투 식량 교환을 위한 동전이 부족하여 다음 인터벌 까지 대기합니다.')

                    next_ip = 'wait_interval'

                    rand_timesleep()

                else:

                    ret_do_g2f = do_g2f(need_chg_tot_gold, city_id)

                    if ret_do_g2f == '::ERROR::':

                        print('식량자원 교환에 실패하여 자동사냥을 중지합니다!!')

                        next_ip = 'exit_auto_attack'

                    else:

                        rand_timesleep()

                        print('소비 식량자원 보충 성공!!')

                        next_ip = 'next'

            else:

                if err_cnt <= 3:

                    err_cnt += 1

                    print('[16]Error발생')

                    timesleep(5)

                    continue

                else:

                    print('3회 이상 에러가 발생하여 자동 사냥을 중단합니다!!')

                    return -1

                

        # 10. 1번으로 반복

        if next_ip == 'next':

            continue

        

        # 11. 도시 사냥 종료 인터벌 대기!!

        if next_ip == 'wait_interval':

            return inteval_sec

        

        # 12. 사냥불가로 인한 사냥 종료(해당 도시는 더이상 공격 안함 리스트에서 팝시킴)

        if next_ip == 'exit_auto_attack':

            return -1


def get_time():

    return str(int(time.time() * 1000))


def rand_timesleep():

    rand_sec = random.randrange(1,2)

    #print('오토검출 방지 대기 : ' + str(rand_sec) + '초')

    time.sleep(rand_sec)

    return


def timesleep(interval_sec):

    print('대기명령 : ' + str(interval_sec) + '초...')

    time.sleep(interval_sec)

    return


def make_cookie():

    gen_cookie = ''

    for l_idx in range(0,32):

        rand_num = random.randrange(1,1000)

        if rand_num > 500:

            gen_cookie += chr(random.randrange(97, 102))

        else:

            gen_cookie += chr(random.randrange(48, 57))

    

    return gen_cookie


def get_html_response(send_url, attempt_type, decode_type = 'utf-8'):

    err_cnt = 0

    

    while True:

        try:

            if attempt_type == 1:

                # 메인 호스트 호출

                conn = http.client.HTTPConnection('m.tapsg.com', 80)

            elif attempt_type == 2:

                # 사용자 서버 호스트 호출

                conn = http.client.HTTPConnection(base_user_host, 80)

            elif attempt_type == 3:

                conn = http.client.HTTPConnection('129.100.170.100', 8181)

            conn.putrequest('GET', send_url)

            

            if attempt_type == 1:

                # 메인 호스트 호출

                conn.putheader('Host','m.tapsg.com')

                conn.putheader('User-Agent','{}/1.10 CFNetwork/548.0.4 Darwin/11.0.0'.format(urllib.parse.quote('손바닥 삼국지')))        

            elif attempt_type == 2:

                # ID종속 서버 호스트 호출

                conn.putheader('Host',base_user_host)

                conn.putheader('User-Agent','Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A405')

            elif attempt_type == 3:

                conn.putheader('Host','129.100.170.100:8181')

                conn.putheader('User-Agent','Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A405')

            conn.putheader('Accept','*/*')

            conn.putheader('Accept-Language','ko-kr')

            conn.putheader('Accept-Encoding','gzip, deflate')

            conn.putheader('Cookie','phpbb3_surfz_k=; phpbb3_surfz_sid=' + base_cookie + '; phpbb3_surfz_u=1')

            conn.putheader('Connection','keep-alive')

            conn.putheader('','')

            conn.endheaders()

            resp = conn.getresponse()

            if str(resp.status).strip() != '200':

                if attempt_type == 3:

                    print('허가되지 않은 장소에서의실행 요청입니다!!')

                    sys.exit()

                print(str(send_url) + ' 페이지에 접속하는데에 실패하였습니다.')

                conn.close()

                resp.close()        

                return '::ERROR::'

            else:

                ret_html_bytes = resp.read()

                ret_html_str = str(ret_html_bytes.decode(decode_type))

                conn.close()

                resp.close()

                return ret_html_str

        except Exception:

            if attempt_type == 3:

                print('허용되지 않은 장소에서의 실행입니다!! 프로그램을 종료합니다!!')

                sys.exit()

            if err_cnt <= 3:

                print('서버연결 응답없음!! 재시도[' + str(err_cnt) + '회')

                err_cnt += 1

                timesleep(30)

                continue

            else:

                print('손바닥 삼국지 서버로 부터 응답이 없습니다. 프로그램 종료!!')

                sys.exit()


def attempt_login():

    print('Payment 체크..')

    payment_chk_url = '/dopayment.php?user=&act=query{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(payment_chk_url, 1)

    if html_source != '::ERROR::':

        print('성공')

    else:

        print('손바닥 삼국지 서버 접속에 실패하였습니다!!\n잠시후 다시 시도하여주세요!!')

        return '::ERROR::'

    

    del(payment_chk_url)

    return 0


def do_g2f(gold_value, city_id):

    # 교환실행

    do_g2f_url = '/game/local_market_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&reso_put=giveput&g2f=' + str(gold_value) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(do_g2f_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        print('[' + str(gold_value) + ']동전을 [' + str(int(gold_value * 7.6923)) + ']식량으로 교환 하는데 성공 하였습니다!!')

        return 'OK'

    else:

        print('동전 ==> 식량 교환에 실패하였습니다!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'

    

def get_soldier(city_id, soldier_type):

    # 병영정보

    soldier_url = '/game/soldier_educate_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(soldier_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'


    if '"code":0' in html_source:

        soldier_num = re.findall('\[' + str(soldier_type) + ',(\d+),\d+\]', html_source)

        if soldier_num:

            soldier_num = int(soldier_num[0])

        else:

            soldier_num = 0

            

        return soldier_num

    else:

        print('사용자 병력 정보 추출에 실패하였습니다!!')

        print('Error Code : ' + html_source)

        return -1


def do_scout(point_x, point_y):

    # 척후병 보유 여부 판단!!

    soldier_num = get_soldier(base_city_id, '2')

    if soldier_num > 0:

        print('척후병 보유수 : ' + str(soldier_num))

    elif soldier_num == 0:

        print('척후병 보유병사가 없으므로 정찰을 진행하지 않습니다!!')

        return 'SKIP'

    else:

        print('척후병 보유수를 가져오는데 실패하였습니다!!')

        return '::ERROR::'

    rand_timesleep()

    

    # 정찰사전정보 수집

    # 본진으로 부터 해당 좌표까지의 거리, 소요자원, 시간, 해당좌표의 ID값 추출 

    scout_info_url = '/game/armament_action_do_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + base_city_id + '&action=do_war&attack_type=3&tai_num=1&area=' + str(point_x) + '&area_x=' + str(point_y) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(scout_info_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        scout_info = re.search('"carry":(\d+),"cost_food":(\d+),"cost_wood":(\d+),"cost_iron":(\d+),"cost_gold":(\d+),"distance":(\d+),"travel_sec":(\d+)',html_source).group()

        scout_info = '&' + scout_info.replace('"', '').replace(':', '=').replace(',', '&')

        cost_food = re.search('cost_food":(\d+),', html_source).group(1)

        print('정찰소요 식량 : ' + str(cost_food))

    else:

        print('정찰지[' + point_x + '/' + point_y + '] 정찰사전정보 수집실패!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'

    rand_timesleep()

    

    # 도시정보 호출 후 식량자원량 추출

    city_resource = get_city_resource(base_city_id)

    if city_resource:

        if city_resource == '::ERROR::':

            return '::ERROR::'

        else:

            city_food = city_resource[0][1]

    else:

        return '::ERROR::'

    rand_timesleep()

    

    # 충분한 식량이 있는지 판단!!

    if int(cost_food) > int(city_food):

        # 없으면 스킵!!

        return '::ERROR::'


    # 정찰

    scout_url = '/game/armament_action_task_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + base_city_id + '&action=war_task&attack_type=3&tai_num=1&area=' + str(point_x) + '&area_x=' + str(point_y) + '&_l=kr&_p=SG-IPHONE-KR' + scout_info + '{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(scout_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        target_id = re.search('"id":(\d+),"cdtype"', html_source).group(1)

        print('정찰지[' + point_x + '/' + point_y + '] ID : ' + target_id + ' : 정찰시도 성공!!')

        return 'OK'

    else:

        print('정찰지[' + point_x + '/' + point_y + '] ID : ' + target_id + ' : 정찰시도 실패!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'

    rand_timesleep()


def get_city_resource(city_id):

    # 도시정보  

    cityinfo_url = '/game/get_cityinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

    html_source = get_html_response(cityinfo_url, 2)

    if html_source == '::ERROR::':

        return '::ERROR::'

    if '"code":0' in html_source:

        city_rs = re.findall('city":\[\d+,\d+,(\d+),\d+,(\d+),\d+,(\d+),\d+,(\d+),', html_source)

        print('동전 : ' + city_rs[0][0] + ', 식량 : ' + city_rs[0][1] + ', 목재 : ' + city_rs[0][2] + ', 철광석 : ' + city_rs[0][3])

        return city_rs

    else:

        print('사용자 정보 추출에 실패하였습니다!!')

        print('Error Code : ' + html_source)

        return '::ERROR::'


def scan_area_all(max_findout_cnt,orangke_type, input_point_x, input_point_y):

        #====지역스캔

        findout_cnt = 1

        err_cnt = 0

        recp_orang = re.compile('\[(\d+),(\d+),([' + str(orangke_type) + ']{1}),\[(\d+)]]')

        recp_food  = re.compile('\[(\d+),(\d+),103,\[(\d+),(\d+),"",""\]\]')

        # 이전 스캔데이터들이 존재하면 파일명을 변경해 백업한다.

        if os.access('orang_data.dat', os.F_OK):

            os.rename('orang_data.dat', 'old_orang_data' + str(time.strftime('%y%m%d%H%M%S')) + '.dat')

        if os.access('food_data.dat', os.F_OK):

            os.rename('food_data.dat', 'old_food_data' + str(time.strftime('%y%m%d%H%M%S')) + '.dat')

        f_orang = open('orang_data.dat', 'w')

        f_food  = open('food_data.dat', 'w')

        for point_y in range(input_point_y, 278, 7):

                for point_x in range(input_point_x, 278, 7):

                        detail_url = '/game/api_world_map.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&x=' + str(point_x) + '&y=' + str(point_y) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                        token_str = get_html_response(detail_url, 2)

                        rand_timesleep()

                        if token_str == '::ERROR::':

                            return '::ERROR::'

                        if findout_cnt <= max_findout_cnt:

                            if '"code":0' not in token_str:

                                    print('[지도스캔좌표 : ' + str(point_x) + '/' + str(point_y) + ']의 스캔에 실패하였습니다.\r\n이 지역을 제외하고 다음지역을 스캔합니다!!')

                                    if err_cnt > 3:

                                            return '::ERROR::'

                                    else:

                                            err_cnt += 1

                            else:

                                    # 오랑캐 스캔!!

                                    find_orang_x_y = recp_orang.findall(token_str)

                                    for idx_x_y in find_orang_x_y:

                                        if idx_x_y:

                                            print(list(idx_x_y), end = '')

                                            print(' ' + list(idx_x_y)[0] + '/' + list(idx_x_y)[1] + ' : 오랑캐 좌표 발견!!')

                                            # 정찰 시도!!

                                            ret_scout = do_scout(list(idx_x_y)[0], list(idx_x_y)[1])

                                            if ret_scout == 'OK':

                                                f_orang.write('[' + list(idx_x_y)[0] + ',' + list(idx_x_y)[1] + ',정찰시도성공]\n')

                                            else:

                                                f_orang.write('[' + list(idx_x_y)[0] + ',' + list(idx_x_y)[1] + ',정찰시도실패]\n')


                                            findout_cnt += 1

                                    # 식량창고(대) 스캔!!

                                    find_food_x_y = recp_food.findall(token_str)

                                    for idx_x_y in find_food_x_y:

                                        if idx_x_y:

                                            print(list(idx_x_y), end = '')

                                            print(' 미점령 식량창고(대) 좌표 발견!!')

                                            f_food.write(str(idx_x_y) + '\n')

                        else:

                            print('찾은 오랑캐 좌표수 : ' + str(findout_cnt-1) + ', 제한 오랑캐 좌표수 : ' + str(max_findout_cnt) + '\r\n사용자 탐색 제한값에 도달하여 탐색을 중지합니다!!')

                            print('찾아진 오랑캐 좌표가 ''orang_dat.dat''파일로 저장되었습니다!')

                            return '0'

        return '0'

        print('찾아진 오랑캐 좌표가 ''orang_dat.dat''파일로 저장되었습니다!')

        f_orang.close()

        f_food.close()


def get_enemy_info_from_file():

    # 파일오픈..

    try:

        f_new = open('orang_final.dat', 'w')

    except Exception:

        print('오랑캐 좌표 분석을 위한 파일을 여는데 실패하였습니다!!')

        return '::ERROR::'

    

    try:

        # 편지함 뒤지기(의미 없음!!) 

        # 로그패턴을 최대한 실제 어플과 비슷하게 하여 오토 검출을 방해하기 위함

        # (해봐야 맘먹고 찾으면 다 걸리겠지만 ㅋㅋ)

        viewmail_url = '/game/message_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&page=1&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

        html_source = get_html_response(viewmail_url, 2)

        if html_source == '::ERROR::':

            return '::ERROR::'

        if '"code":0' in html_source:

            pass

        else:

            print('정찰 정보를 추출 하는데 실패하였습니다.')

            print('viewmail_url : ' + html_source)

            return '::ERROR::'

        rand_timesleep()

        

        # 정찰결과 리스팅

        scout_info_dat = ''

        while True:

            scout_list_url = '/game/war_result_list_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&page=1&type=3&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

            html_source = get_html_response(scout_list_url, 2)

            if html_source == '::ERROR::':

                return '::ERROR::'

            rand_timesleep()

            if '"code":0' in html_source:

                scout_info_dat = html_source

                # 현재 추출되어진 ID들을 결과함에서 삭제함.. 페이지가 10page 맥스이고 뒤로 밀려 어쩔수 없음..

                scout_del_id = re.findall('"id":(\d+),', html_source)

                

                # 편지함에 저장된 정찰정보의 해당 좌표(정찰이 성공한 좌표만)별 ID값 추출

                if len(scout_del_id):

                    # 제대로 검출 되면!!

                    for list_item in scout_del_id:

                        print('검출된 ID : ' + list_item)

                        point_x = re.search('{"id":' + list_item + ',.+?"dx":(\d+),"dy":(\d+),', scout_info_dat).group(1)

                        point_y = re.search('{"id":' + list_item + ',.+?"dx":(\d+),"dy":(\d+),', scout_info_dat).group(2)

                        print('point_x : ' + point_x + ', point_y : ' + point_y)

                        scout_detail_url = '/game/war_result_info_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&id=' + str(list_item) + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                        html_source = get_html_response(scout_detail_url, 2)

                        if html_source == '::ERROR::':

                            return '::ERROR::'

                        if '"code":0' in html_source:

                            str_token = str(html_source)

                            if '\\uc0b0\\ub3c4\\uc801' in str_token:

                                san_num = '1'

                            else:

                                san_num = '0'

                            if '\\ud654\\uc801' in str_token:

                                hwa_num = '1'

                            else:

                                hwa_num = '0'

                            write_str = '[' + point_x + ',' + point_y + ',' + '산도적(' + san_num + '),화적(' + hwa_num + ')]' 

                            print(write_str)

                            f_new.write(write_str + '\n')

                            rand_timesleep()

                            if int(hwa_num) == 0 and int(san_num) > 0:

                                add_friend_url = '/game/api_fav.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&act=addreport&wid=' + str(list_item) + '&cat=2&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                                html_source = get_html_response(add_friend_url, 2)

                                if html_source == '::ERROR::':

                                    return '::ERROR::'

                                if '"code":0' in html_source:

                                    print(write_str + 'Only 산도적 오랑캐 ==> 친구추가완료!!')

                                else:

                                    print(write_str + 'Only 산도적 오랑캐 ==> 친구추가실패!!')

                                    print('add_friend_url : ' + html_source)

                                rand_timesleep()

                        else:

                            print('scout_detail_url Error : ' + html_source)

                else:

                    print('[' + point_x + '/' + point_y + '] 병력상세정보 검출 실패!!')

                    print('scout_detail_url : ' + scout_detail_url)


                if len(scout_del_id):

                    del_str = ''

                    del_id_cnt = len(scout_del_id)

                    while len(scout_del_id):

                        del_pop_item = str(scout_del_id.pop())

                        if len(scout_del_id) == 0:

                            del_str += del_pop_item

                        else:

                            del_str += del_pop_item + '%2C'

                    scout_del_url = '/game/war_result_list_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&action=delete&id=' + del_str + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                    #print('scout_del_url : ' + scout_del_url)

                    html_source = get_html_response(scout_del_url, 2)

                    if html_source == '::ERROR::':

                        return '::ERROR::'

                    rand_timesleep()

                    if '"code":0' in html_source:

                        print('정찰완료 정보' + str(del_id_cnt) + '개 삭제 완료!!')

                    else:

                        print('정찰완료 정보' + str(del_id_cnt) + '개 삭제 실패!!')

                        print('scout_del_url : ' + scout_del_url)

                    print('다음 정찰결과 정보 추출..')

                else:

                    print('모든 정찰결과 정보 추출 완료!!')

                    break

            else:

                print('정찰결과 리스트를 불러오는데 실패하였습니다. 프로그램을 종료합니다!!')

                print('Error Code : ' + html_source)

                return '::ERROR::'


    finally:

        print('정찰결과 분석 정보가 ''orang_final.dat''에 저장되었습니다!!')

        f_new.close()


# 메인함수 시작!!


# 장소 인증

chk_auth()


print("""

***************************************************************

손바닥삼국지 도우미 Ver 0.31(alpha) - by hElLoOnG(2012.04.02)

***************************************************************

*주의사항

*이 프로그램 사용으로 인하여 발생하는 불이익에 대하여

*개발자는 어떠한 책임도 지지 않습니다.

*

*기타 문의 및 버그 수정 요청은 살포시 넣어둬 주세요 ㅋㅋ 

***************************************************************

""")


# 쿠키 생성

base_cookie = make_cookie()

print('Session 생성 : ' + base_cookie)


# 사용자 아이디/패스워드 입력부(입력안하면 기본 아이디로 진행)

temp_user_id = input('손바닥삼국지 ID : ')

if str(temp_user_id).strip() != '':

    base_user_id = temp_user_id

    print('입력된 사용자 ID : ' + base_user_id)

else:

    print('ID가 입력되지 않았습니다!!')

    sys.exit()

temp_user_pw = input('손바닥삼국지 PW : ')

if str(temp_user_pw).strip() != '':

    base_user_pw = temp_user_pw

    print('입력된 사용자 PW : ' + base_user_pw)

else:

    print('PW가 입력되지 않았습니다!!')

    sys.exit()


# 실제 앱에서 일어나는 의미없는 체크

print('손바닥 삼국지 서버로 접속을 시도합니다...')

html_source = attempt_login()

if html_source == '::ERROR::':

    sys.exit()


rand_timesleep()

    

# 사용자 서버 정보 추출

print('사용자의 손바닥 삼국지 서버 정보를 추출합니다...')

get_server_url =  '/info.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&user=' + base_user_id + '&action=login&pvp=0&code=a1c1ef3363ae6f52d8e823ecd7d62da618a98c43&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(get_server_url, 1)

if html_source == '::ERROR::':

    sys.exit()

if '"code":0' in html_source:

    base_user_host = re.search('k(\d+)\.tapsg\.com', html_source).group()

    print('사용자 서버 추출 성공 : ' + base_user_host)

else:

    print('사용자 서버정보 추출에 실패하였습니다!!\nID, PW를 확인하고 다시 시도하여 주세요!!')

    print('Error Code : ' + html_source)

    sys.exit()


# 실제 인증 키값 추출

print('손바닥 삼국지 인증키 값을 추출합니다...')

login_url = '/game/login_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&username=' + base_user_id + '&password=' + base_user_pw + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

print('login_url : ' + login_url)

html_source = get_html_response(login_url, 2)

if html_source == '::ERROR::':

    sys.exit()

if '"code":0' in html_source:

    base_token = re.search('key":"(\\w+)"}',html_source).group(1)

    print('사용자 인증키 추출 성공 : ' + base_token)

else:

    print('사용자 인증키 추출에 실패하였습니다!!')

    print('Error Code : ' + html_source)

    sys.exit()


# 사용자 정보 추출

#userinfo_url : jsonp1333982142599({"code":0,"ret":{"user":{"id":20440,"nick":"helloong","nationid":1,"level":39,"money":100,"guild":"\uace0\ud55c\uc74d","guildid":13,"gpower":5,"gflag":64,"protection":0,"p_end":1332411629,"status":0,"city":[{"id":23764,"name":"\ub69d\ub531\uc131","landtype":5,"x":264,"y":133},{"id":24410,"name":"\ub69d\ub531\uc1312","landtype":5,"x":265,"y":133}],"conq":[0,0,null,5],"gift":[],"pvp":0},"events":[{"id":1,"icon":"gem.jpg","name":"\uc131\uc2e4\ud55c \ub2f9\uc2e0\uc744 \uc704\ud55c \ubcf4\uc0c1! [5\/7\uc77c]","desc":"<b>\uc77c\uc77c \uc120\ubb3c<\/b>\uc740 \ub85c\uadf8\uc778 \ud6c4 \ubc1b\uc73c\uc2e4 \uc218 \uc788\uc2b5\ub2c8\ub2e4. 7\uc77c\uac04 \uc5f0\uc18d \ub85c\uadf8\uc778\uc744 \ud558\uc2dc\uba74 <b>\ub3d9\uc6d0\ub839(7\uc77c)<\/b>\uc744 \ub4dc\ub9bd\ub2c8\ub2e4!"},{"id":2,"icon":"0.png","name":"\ub4f1\uae09\uaca9\ucc28 \ubcf4\ud638\uc0c1\ud0dc","desc":"\uba3c\uc800 \uacf5\uaca9\ud558\uc9c0 \uc54a\ub294 \uc774\uc0c1, 10\ub4f1\uae09\uc774\uc0c1\uc758 \uc720\uc800\ub85c\ubd80\ud130 \ubcf4\ud638 \ubc1b\uc2b5\ub2c8\ub2e4. \uc774 \ubcf4\ud638\ub294 \ub85c\uadf8\uc544\uc6c3\ud6c4 24\uc2dc\uac04\uc774 \uc9c0\ub098\uba74 \uc790\ub3d9\uc73c\ub85c \ucde8\uc18c\ub429\ub2c8\ub2e4."}],"status":{"invite":1,"ver":0.9,"vs":1.25,"vr":0.5,"ce":1,"he":1}}})

print('사용자 정보 추출')

userinfo_url = '/game/get_userinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(userinfo_url, 2)

if html_source == '::ERROR::':

    sys.exit()

if '"code":0' in html_source:

    base_city_id = re.search('"city":\[\{"id":(\d+),"name":',html_source).group(1)

    city_id_all  = re.findall('"id":(\d+),"name"', html_source)

    print('사용자 본성 ID : ' + base_city_id)

    print('사용자 전체성 ID : ', end ='')

    print(city_id_all)

else:

    print('사용자 정보 추출에 실패하였습니다!!')

    print('Error Code : ' + html_source)

    sys.exit()


# 사용자 테스크 정보

usertask_url = '/game/system_task_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&action=task_list&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(usertask_url, 2)

if html_source == '::ERROR::':

    sys.exit()


# 도시정보 호출

city_resource = get_city_resource(base_city_id)

if city_resource == '::ERROR::':

    sys.exit()


# cd 정보??

cdinfo_url = '/game/get_cdinfo_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + base_city_id + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

html_source = get_html_response(cdinfo_url, 2)

if html_source == '::ERROR::':

    sys.exit()


# 사용자 희망 작업 선택!!

print("""

***************************************************************

* 메뉴 선택

***************************************************************

* 1: 오랑캐 좌표 및 현시간 미점령 식량창고(대) 좌표 스캔!!

*    본성에 척후병이 약 100명정도 보유 하셔야 합니다!!

*    초반 성별 식량은 15만 이상 맞춰 주세요!!

*

* 2: ID 정찰결과 함에 존재하는 병력정보 검색(Only산도적 좌표 자동친구추가)

* 3: 도시별 연무장 소문 수집 작업(연무장 레벨 최소 16이상, 고용 공간 필요)

* 4: 친구추가 되어있는 오랑캐 자동사냥

* 5: 종료

***************************************************************


""")


which_way = int(input('원하시는 작업을 선택하여주세요[1 - 4] : '))


if which_way == 1:

    # 오랑캐 추출 갯수 입력부

    base_find_cnt = int(input('얼마나 많은 오랑캐 좌표를 찾길 원하세요?(1-' + str(base_max_cnt) + ') : '))

    if (base_find_cnt < 1) or (base_find_cnt > base_max_cnt):

        print('입력값의 범위가 잘못되었습니다.(입력값은 숫자 1 부터 ' + str(base_max_cnt) + '사이 값이어야 합니다.')

        sys.exit()

    base_find_type = int(input('어떤 종류의 오랑캐를 찾고 싶으세요(1-6)??\n(1:별6개 오랑캐,2:별5개 오랑캐,3:별4개 오랑캐, ...): '))

    if (base_find_type < 1) or (base_find_type > 6):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 1부터 6사이 값이어야 합니다!!')

        sys.exit()

    point_x = int(input('지도상 x축 스캔시작 좌표 입력[4 - 270](기본값 4) : '))

    if (point_x < 4) or (point_x > 270):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 4부터 270사이 값이어야 합니다!!')

        sys.exit()

    point_y = int(input('지도상 y축 스캔시작 좌표 입력[4 - 270](기본값 4) : '))

    if (point_y < 4) or (point_y > 270):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 4부터 270사이 값이어야 합니다!!')

        sys.exit()

    # 지도 스캔 및 오랑캐/식량창고(대) 좌표추출

    print('지도 스캔작업을 시작합니다...')

    ret_val = scan_area_all(base_find_cnt,base_find_type,point_x,point_y)

    if ret_val == '::ERROR::':

        sys.exit()

elif which_way == 2:

    print('입력하신 ID 정찰결과 함으로 부터 병력정보 및 친구추가 작업을 진행합니다...')

    ret_str = get_enemy_info_from_file()

elif which_way == 3:

    print('다음 도시의 연무장에 1시간 5분마다 모든 도시의 한잔하기를 시행합니다!!')

    print('실행중 서버가 불안정 하거나 한잔하기에 필요한 동전이 부족하면 자동 종료됩니다!!')

    print('대상도시 ID : ', end=''); print(city_id_all)

    #GET /game/gen_conscribe_api.php?jsonpcallback=jsonp1333983704456&_=1333983724728&key=c9808b7af18f45e2e6e599ef6a0fcc02&city=23764&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #chk_somedrink_url : jsonp1333985951179({"code":0,"ret":{"price":66,"type":3}})

    #GET /game/gen_conscribe_api.php?jsonpcallback=jsonp1333983704457&_=1333983726653&key=c9808b7af18f45e2e6e599ef6a0fcc02&city=23764&action=pub_process&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #buy_response : jsonp1334004741746({"code":0,"ret":{"gold":102706,"price":8545,"refresh":3600,"hero":{"gid":205,"p":21,"i":8,"c1":11,"g":3,"c2":300},"rumor":0}})

    #hero gid:아이디, p:공격력, i:지혜력, c1:방어력, c2: 통솔력


    int_drink_tick = 0

    int_mod_sec = 3780 # 1시간 3분


    try:

        f_drink_name = 'drink_log_' + time.strftime('%y%m%d%H%M') + '.dat'

        while True:

            if (int_drink_tick == 0) or (int_drink_tick % int_mod_sec == 0):

                file_drink = open(f_drink_name, 'a')

                for city_id_item in city_id_all:

                    print('현재시간 : ' + time.strftime('%Y-%m-%d %H:%M:%S'))

                    chk_somedrink_url = '/game/gen_conscribe_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id_item + '&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                    print('chk_somedrink_url : ' + chk_somedrink_url)

                    html_source = get_html_response(chk_somedrink_url, 2)

                    file_drink.write('chk_somedrink_url : ' + chk_somedrink_url + '\n')

                    if html_source == '::ERROR::':

                        sys.exit()

                    if '"code":0' in html_source:

                        if '"refresh":' in html_source:

                            need_refresh_t = int(re.search('"refresh":(\d+),"hero"', html_source).group(1))

                            print('도시[' + city_id_item + ']의 한잔하기 남은 대기시간 : ' + str(need_refresh_t) + '초 입니다.')

                        else:

                            need_refresh_t = 0

                        need_money = re.search('"price":(\d+),"type"', html_source).group(1)

                        file_drink.write('OK[chk] : ' + str(html_source) + '\n')

                    else:

                        print('도시[' + city_id_item + ']의 소문모으기 준비 작업에 실패하였습니다!!')

                        print('Error Code : ' + html_source)

                        file_drink.write('Err[chk] : ' + str(html_source) + '\n')

                    

                    if need_refresh_t == 0:

                        get_city_money = get_city_resource(city_id_item)

                        print('remain money : ' + get_city_money[0][0] + ', need money : ' + need_money)

                        if int(need_money) > int(get_city_money[0][0]):

                            print('한잔하기에 필요한 동전이 부족하여 작업을 종료합니다!!')

                            sys.exit()

                         

                        buy_somedrink_url = '/game/gen_conscribe_api.php?jsonpcallback=jsonp' + get_time() + '&_=' + get_time() + '&key=' + base_token + '&city=' + city_id_item + '&action=pub_process&_l=kr&_p=SG-IPHONE-KR{}HTTP/1.1'.format(urllib.parse.quote(' '))

                        print('buy_somedrink_url : ' + buy_somedrink_url)

                        html_source = get_html_response(buy_somedrink_url, 2)

                        file_drink.write('buy_somedrink_url : ' + buy_somedrink_url + '\n')

                        if html_source == '::ERROR::':

                            sys.exit()

                        if '"code":0' in html_source:

                            print('buy_response : ' + html_source)

                            file_drink.write('OK[buy] : ' + html_source + '\n')

                        else:

                            print('도시[' + city_id_item + ']의 소문모으기 준비 작업에 실패하였습니다!!')

                            print('Error Code : ' + html_source)

                            file_drink.write('Err[chk] : ' + str(html_source) + '\n')

    

                int_drink_tick = 0

                int_drink_tick += 1

                

                time.sleep(1)

                file_drink.close()

            else:

                #print('현재시간 : ' + time.strftime('%Y-%m-%d %H:%M:%S'))

                int_drink_tick += 1

                #print('남은대기 초 : ' + str(int_drink_tick) + '/' + str(int_mod_sec))

                time.sleep(1)

    finally:

        file_drink.close()

elif which_way == 110:

    while True:

        print('사용자 인증키 : ' + base_token)

        print('현재시간_1 : ' + get_time())

        print('현재시간_2 : ' + get_time())

        print('사용자 본성 ID : ' + base_city_id)

        print('사용자 전체성 ID : ', end ='')

        print(city_id_all)

        input_send_str = str(input('send_str(quit is "q") : '))

        if len(input_send_str) > 1:

            input_send_str = input_send_str.format(urllib.parse.quote(' '))

        if input_send_str == 'q':

            break

        html_source = get_html_response(input_send_str, 2)

        if html_source == '::ERROR::':

            sys.exit()

        print('Response : ')

        print(html_source)

    print('테스트 종료!!')

elif which_way == 4:

    

    city_id_loop = ''

    

    # 질문1

    # 오랑캐 타입!! 어떤 오랑캘 잡을지!!

    type_orang = str(input('친구추가된 오랑캐중 어떤 종류의 오랑캐를 공격하고 싶으세요(1-6)??\n(1:별6개, 2:별5개, 3:별4개, 4:별3개, 5:별2개, 6:별1개): '))

    if (type_orang < '1') or (type_orang > '6'):

        print('입력값의 범위가 잘못되었습니다.(입력값은 숫자 1 부터 6사이 값 이어야 합니다.')

        sys.exit()

    # 질문2

    # 공격 병력타입(중보 : 11, 친위 : 15)

    type_soldier = str(input('어떤 병력으로 오랑캐를 공격하시겠습니까??\n(11: 중보병, 15: 친위기병): '))

    if (type_soldier != '11') and (type_soldier != '15'):

        print('입력값의 범위가 잘못되었습니다.(입력값은 11 또는 15 이어야 합니다.')

        sys.exit()

    # 질문3

    # 공격 병력수 100단위로 입력!!(6성 평균 기준 : 중보 : 800, 친위 : 500)

    num_soldier = int(input('몇명의 병력을 공격에 동원하고 싶으세요\n(100단위 입력, 최소300-최대800): '))

    if (num_soldier < 300) or (num_soldier > 800):

        print('입력값의 범위가 잘못되었습니다!!(입력값은 숫자 300부터 800사이 값이어야 합니다!!')

        sys.exit()

    if (num_soldier % 100) != 0:

        print('입력값의 범위가 잘못되었습니다!!(입력값은 100단위로 이루어져야 합니다!!')

        sys.exit()

    

    city_id_loop = copy.deepcopy(city_id_all)


    while city_id_loop:

        # 리스트 마지막 item을 검출!!

        last_city_id = city_id_loop[len(city_id_loop) - 1]

        # 기본대기시간  10분 60초 * 10분 = 600초

        ret_max_timesleep = 600

        

        for idx_city_id in city_id_loop:

            

            print('[' + idx_city_id + ']성의 자동사냥을 시작합니다...')

            

            ret_max_timesleep = auto_attack(idx_city_id, ret_max_timesleep, type_orang, type_soldier, num_soldier)

            # 리턴값 판별!!

            if ret_max_timesleep < 0:

                # 해당 성 자동 사냥 종료

                city_id_loop.pop(city_id_loop.index(idx_city_id))

                print('[' + idx_city_id + ']성은 자동사냥 목록에서 제외됩니다.')

            else:

                if idx_city_id == last_city_id:

                    print('자동사냥 목록에 있는 모든 성의 자동 사냥 턴이 완료 되었습니다!!')

                    print('인터벌 대기 후 재시작 합니다!!')

                    timesleep(300)

                else:

                    print('[' + idx_city_id + ']성의 자동사냥 턴이 완료 되었습니다!!')

                    print('다음성[' + city_id_loop[city_id_loop.index(idx_city_id) + 1] + ']의 자동사냥을 시작합니다!!')

                    rand_timesleep()

    print('자동 사냥 목록에 남은 성이 없습니다!!')

    input('아무키나 누르시면 자동사냥을 종료합니다.')

    sys.exit()


    # 12. 동전 동괴화 작업!!

    #GET /game/get_userinfo_api.php?jsonpcallback=jsonp1334481191259&_=1334481287964&key=a79a44877dece79457f4e78152c3b08f&action=exp&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #GET /game/get_userinfo_api.php?jsonpcallback=jsonp1334481191260&_=1334481290297&key=a79a44877dece79457f4e78152c3b08f&action=g_cd&_l=kr&_p=SG-IPHONE-KR HTTP/1.1

    #GET /game/gold_local_market_api.php?jsonpcallback=jsonp1334481191261&_=1334481299554&key=a79a44877dece79457f4e78152c3b08f&city=23764&type=2&num=1&_l=kr&_p=SG-IPHONE-KR HTTP/1.1


elif which_way == 5:

    print('손바닥삼국지 도우미를 종료합니다.')

    sys.exit()


'Study > python' 카테고리의 다른 글

wxpython webview test  (0) 2013.10.05
[연습중]MK RSS 파싱  (0) 2013.09.23
[연습]Python regular expression & sqlite  (0) 2013.09.22
[펌]Unicode In Python, Completely Demystified  (0) 2013.09.18
python ODBC 연결시~  (0) 2013.01.26
Posted by 땡보