2017-01-07 1 views
1

내가 뭘하는지에 대한 간단한 개요 나는 자바 스크립트를 렌더링하고 안드로이드 Webview를 사용하고 그것을 분석하는 자바 스크립트에서 HTML을 읽고 사용하고 있습니다.안드로이드 WebView 원하는 HTML을 반환하지 않습니다

현재 Sport Chek라는 웹 사이트에서 HTML을 가져 오는 중 문제가 있습니다.

public class SportChekSearch extends SearchQuery{ 

public Elements finalDoc; 
private ArrayList<Item> processed; 
private final Handler uiHandler = new Handler(); 
public int status = 0; 

//This basically is just so that the class knows which Activity we're working with 
private Context c; 

protected class JSHtmlInterface { 
    @android.webkit.JavascriptInterface 
    public void showHTML(String html) { 
     final String htmlContent = html; 

     uiHandler.post(
       new Runnable() { 
        @Override 
        public void run() { 
         Document doc = Jsoup.parse(htmlContent); 
        } 
       } 
     ); 
    } 
} 

/** 
* Constructor method 
* @param context The context taken from the webview (So that the asynctask can show progress) 
*/ 
public SportChekSearch(Context context, String query) { 

    final Context c = context; 

    try { 
     final WebView browser = new WebView(c); 
     browser.setVisibility(View.INVISIBLE); 
     browser.setLayerType(View.LAYER_TYPE_NONE, null); 
     browser.getSettings().setJavaScriptEnabled(true); 
     browser.getSettings().setBlockNetworkImage(true); 
     browser.getSettings().setDomStorageEnabled(true); 
     browser.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); 
     browser.getSettings().setLoadsImagesAutomatically(false); 
     browser.getSettings().setGeolocationEnabled(false); 
     browser.getSettings().setSupportZoom(false); 
     browser.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); 
     browser.addJavascriptInterface(new JSHtmlInterface(), "JSBridge"); 

     browser.setWebViewClient(
       new WebViewClient() { 

        @Override 
        public void onPageStarted(WebView view, String url, Bitmap favicon) { 
         super.onPageStarted(view, url, favicon); 
        } 

        @Override 
        public void onPageFinished(WebView view, String url) { 
         browser.loadUrl("javascript:window.JSBridge.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');"); 
        } 
       } 
     ); 


      browser.loadUrl("https://www.sportchek.ca/search.html#q=" + query.replaceAll(" ", "+") + "&lastVisibleProductNumber=3"); 
      browser.loadUrl(browser.getUrl()); 
      final String link = browser.getUrl(); 
      new fetcher(c).execute(link); 



    } 
    catch(Exception e){ 
     e.printStackTrace(); 
    } 

    //Get the link from the WebView, and save it in a final string so it can be accessed from worker thread 


} 

/** 
* This subclass is a worker thread meaning it does work in the background while the user interface is doing something else 
* This is done to prevent "lag". 
* To call this class you must write fetcher(Context c).execute(The link you want to connect to) 
* 
*/ 
class fetcher extends AsyncTask<String, Void, Elements> { 

    Context mContext; 
    ProgressDialog pdialog; 

    public fetcher(Context context) { 
     mContext = context; 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     pdialog = new ProgressDialog(mContext); 
     pdialog.setTitle(R.string.finding_results); 
     pdialog.setCancelable(false); 
     pdialog.show(); 
    } 

    //This return elements because the postExecute() method needs an Elements object to parse its results 
    @Override 
    protected Elements doInBackground(String... strings) { 

     //You can pass in multiple strings, so this line just says to use the first string 
     String link = strings[0]; 

     //For Debug Purposes, Do NOT Remove - **Important** 
     System.out.println("Connecting to: " + link); 

     try { 
      doc = Jsoup.connect(link) 
        .ignoreContentType(true) 
        .userAgent("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") 
        .timeout(10000) 
        .get(); 


      finalDoc = doc.select("body section.product-grid-wrapper"); 

      System.out.println(finalDoc.toString()); 



     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return finalDoc; 
    } 


    @Override 
    protected void onPostExecute(Elements result) { 


     //This line clears the list of info in the Search activity 
     //I should probably be using a getter method but adapter is a static variable so it shouldn't matter 


     //parse seperates document into elements 
     //crunch results formats those elements into item objects 
     //I am saving the result of this to an ArrayList<Item> called "processed" 
     processed = crunchResults(result); 

     //For debug purposes, do NOT remove - **Important** 
     System.out.println(processed.size() + " results have been crunched by Sport Chek."); 

     //Adds all of the processed results to the list of info in Search activity 
     ClothingSearch.adapter.addAll(processed); 


     //For debug purposes, do NOt remove - **Important 
     System.out.println("Adapter has been notified by Sport Chek."); 

     //Closes the progress dialog called pdialog assigned to the AsyncTask 

     pdialog.dismiss(); 

     ClothingSearch.adapter.notifyDataSetChanged(); 
     SearchQueueHandler.makeRequest(mContext, processed, SearchQueueHandler.CLOTHING_SEARCH); 




    } 
} 



    public ArrayList<Item> crunchResults(Elements e){ 

    ArrayList<Item> results = new ArrayList<Item>(); 

    try { 

     for (int i = 0; i < e.size(); i++) { 

      Element ele = e.get(i); 


      String link = "https://www.sportchek.ca" + ele.select(" a.product-grid__link").attr("href"); 
      System.out.println("https://www.sportchek.ca" + ele.select(" a.product-grid__link").attr("href")); 
      String title = ele.select(" span.product-title-text").text(); 

      String pricestring = ele.select(" span.product-price__wrap").text(); 
      price = Double.parseDouble(pricestring.substring(pricestring.lastIndexOf("$"))); 
      System.out.println(pricestring); 

      //******************************************* 

      String store = "Sport Chek"; 



       //Adds the formatted item to an ArrayList of items 
       results.add(new Item(title, store, price, link)); 


      //Prints the object's to String to console 
      //For debug purposes, do NOT remove - **Important 
      System.out.println(results.get(i).toString()); 
     } 
    } catch (Exception a){ 
     a.printStackTrace(); 
    } 

    return results; 
} 

public int getStatus(){ 
    return status; 
} 

}

두 가지 관련 방법은 내 AsyncTask를에 doInBackground을하며 crunchResults 방법 : 여기

내 SportChekSearch 클래스에 대한 코드입니다.

Desired Result

그러나 위의 코드를 실행할 때와를 사용하여 : 여기

내가 실제 웹 사이트 (원하는 결과를) Ctrl 키 + 시프트 + I를 사용에서 얻는 결과입니다 println은 태그 섹션 class = "product-grid-wrapper"에 대한 결과입니다.

<section class="product-grid-wrapper"> 
<ul data-module-type="SearchProductGrid" class="product-grid__list product-grid__list_quickview"> 
<!-- #product-grid__item-template --> 
</ul> 
</section> 

누구나 내가 원하는 결과를 얻지 못하는 이유를 알아낼 수 있습니까?

은 모든 도움은

편집을 감사 : println 메소드 데이터가 수집 된이 특정 검색에 대한 링크가 당신이 실제로 얻고있는 것은 서버가 보낸 실제 HTML은 마치 https://www.sportchek.ca/search.html#q=men+coat&lastVisibleProductNumber=3

답변

0

했다 , 그리고 '원하는 결과'는 자바 스크립트가 실행 된 후 DOM이 어떻게 생겼는지 보여줍니다.

'실제'는 Chrome에서 '소스보기'를 사용하는 경우 표시되는 반면, '원하는 결과'는 Chrome의 DOM 속성을 사용하는 경우 표시됩니다.

더 자세히 살펴보면 실제로 브라우저에서 HTML을 가져 오지 않는다는 것을 알 수 있습니다. JSoup의 Connection 객체를 사용하여 직접 HTML을 가져옵니다. 불행히도, 그것은 자바 스크립트를 실행하지 않을거야.

대신 JavaScript를 실행 한 후에 WebView에서 HTML을 가져와야합니다. 그렇게 할 수있는 가능한 방법을 위해, 그리고 How do I get the web page contents from a WebView?

를 참조하십시오, 당신은 당신이 위의 코드까지 스크롤하면, 당신은 모든 것을 볼 수 있습니다 당신은

Jsoup.parse(html); 
+0

와 JSoup에 그에게서 얻는 HTML을 제공 불행히도 거기에 이미있다 –

+0

흠 ... 좋아, 어쩌면 당신은 자바 스크립트를 실행하게 지연을 소개해야합니까? – GreyBeardedGeek

+0

HtmlUnit 드라이버와 함께 Selenium을 사용하려고 생각했지만 제대로 작동하지 않는 것 같습니다. 이것이 좋은 해결책일까요? 그렇다면 내가 시작할 수있는 자원이 있습니까? –

관련 문제