마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 DOM파싱 속도 줄이는 방법

0 추천
public class GetFanList extends AsyncTask<Void, Void, ArrayList<DrawerItem>> {

    @Override
    protected ArrayList<DrawerItem> doInBackground(Void... voids) {
        ArrayList<DrawerItem> tmp= new ArrayList<>();
        try {
            // 로그인 페이지 접속
            Connection.Response loginPageResponse = Jsoup.connect("https://fans.jype.com/Default")
                    .timeout(3000)
                    .header("Origin", "https://fans.jype.com/")
                    .header("Referer", "https://fans.jype.com/Default")
                    .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .header("Accept-Encoding", "gzip, deflate, br")
                    .header("Accept-Language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
                    .method(Connection.Method.GET)
                    .execute();

            Document loginPageDocument = loginPageResponse.parse();

            //Form Data for Token
            String __LASTFOCUS = loginPageDocument.select("#__LASTFOCUS").val();
            String __EVENTTARGET = loginPageDocument.select("#__EVENTTARGET").val();
            String __EVENTARGUMENT = loginPageDocument.select("#__EVENTARGUMENT").val();
            String __VIEWSTATE = loginPageDocument.select("#__VIEWSTATE").val();
            String __VIEWSTATEGENERATOR = loginPageDocument.select("#__VIEWSTATEGENERATOR").val();
            String __EVENTVALIDATION = loginPageDocument.select("#__EVENTVALIDATION").val();

            // Window, Chrome의 User Agent.
            String userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36";

            // 전송할 폼 데이터
            Map<String, String> data = new HashMap<>();
            data.put("__LASTFOCUS", __LASTFOCUS);
            data.put("__EVENTTARGET", __EVENTTARGET);
            data.put("__EVENTARGUMENT", __EVENTARGUMENT);
            data.put("__VIEWSTATE", __VIEWSTATE); // 로그인 페이지에서 얻은 토큰들
            data.put("__VIEWSTATEGENERATOR", __VIEWSTATEGENERATOR);
            data.put("__EVENTVALIDATION", __EVENTVALIDATION);
            data.put("txtUserID", "chad76");
            data.put("txtPassword", "164138");
            data.put("btnLogin", "LOGIN");


            System.out.println(data);

            Connection.Response loginPageResponse_for_cookies = Jsoup.connect("https://fans.jype.com/Default")
                    .timeout(3000)
                    .header("Origin", "https://fans.jype.com/")
                    .header("Referer", "https://fans.jype.com/Default")
                    .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .header("Accept-Encoding", "gzip, deflate, br")
                    .header("Accept-Language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
                    .userAgent(userAgent)
                    .data(data)
                    .method(Connection.Method.POST)
                    .execute();

            // 로그인 성공 후 얻은 쿠키.
            Map<String, String> loginTryCookie = loginPageResponse_for_cookies.cookies();

            Connection.Response response = Jsoup.connect("https://fans.jype.com/MyFans")
                    .userAgent(userAgent)
                    .header("Origin", "https://fans.jype.com/")
                    .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .header("Accept-Encoding", "gzip, deflate, br")
                    .header("Accept-Language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
                    .cookies(loginTryCookie)
                    .method(Connection.Method.GET)
                    .execute();


            Document source = response.parse();
            Elements elements = source.select(".col-lg-6");
            for (org.jsoup.nodes.Element element : elements) {
                org.jsoup.nodes.Element element1 = element.select("img[class=img-responsive center-block]").first();
                String name= element1.attr("src");
                element1 = element.select("img[class=img-responsive center-block]").get(1);
                String img = element1.attr("src");
                String fansName = element.select("a").first().attr("href");
                tmp.add(new DrawerItem(img,name,fansName));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            for(int i=0;i<tmp.size();i++) {
                Connection.Response response = Jsoup.connect("https://fans.jype.com/" + tmp.get(i).getBoardName())
                        .method(Connection.Method.GET)
                        .execute();

                Document source = response.parse();
                String board_name = source.getElementById("MainContent_ctl00_divMainPageSummary").getElementById("MainContent_ctl00_lnkReadMore").attr("href").split("=")[1];
                tmp.get(i).setBoardName(board_name);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        return tmp;
    }
}

위는 파싱클래스 입니다. 약 17초 정도 나옵니다. 많이 부족한 소스입니다. 어떻게 해결해야 될까요? 

프로그래밍잘하고싶은나 (390 포인트) 님이 2018년 12월 18일 질문

2개의 답변

0 추천
제대로 보진 않았지만, 로그인을 한 뒤에 목록을 가져오는 것 같네요.

로그인의 시간과 목록을 가져오는 시간을 나누어 보세요.
로그인은 앱 실행과 동시에 백그라운드에서 처리하고, Cookie를 저장해 놓은 후에,
필요할 때, 해당 목록 화면을 가져와서 파싱하면 훨씬 빨라질 것 같네요.

해킹이나 크롤링이 아니라면,

실제로는 이런 식으로 가져오지 않고, API 서버를 만들어서 API 서버에서 원하는 값만 json 형태로 받아와야 하는게 정상입니다. 실제로 필요한 것은 세개의 데이터가 있는 목록인데, 쓸데없이 많은 html 태그를 다 받아서와서 해당하는 것만 취하는 거 아닙니까?
Will Kim (43,170 포인트) 님이 2018년 12월 18일 답변
0 추천
코드상 특별히 오래걸릴만한건 안보입니다.

 for(int i=0;i<tmp.size();i++)  로 각 board 마다 응답을 받는듯 한데, 이 부분을 최소한의 board만 받도록 변경하고, 필요시에 해당 board를 받도록 변경 해 보시는게 좋을 듯 합니다.
익명사용자 님이 2018년 12월 18일 답변
...