КОТ++
Прикладное программирование
Системное программирование
Программирование микроконтроллеров

Мы наблюдаем общество, которое все больше зависит от машин, но при этом использует их все неэффективнее. (с) Дуглас Рашкофф

Поиск по тегам

Опубликовано
Комментарии 0

Не так давно передо мной стояла серьёзная задача парсинга данных с некоторых сайтов. Проблема была в том, что обычный HTTP запрос не поможет, т.к. нужно, чтобы на странице отработал javascript и построил данные на странице, чтобы мы потом их спарсили. С помощью обычного HTTP запроса возвращается почти пустая страница. Выход очевиден - делать запрос через браузер, ждать пока отработают скрипты на странице и передавать исходный код уже сформированной страницы парсеру. Долго я гулял по гуглу прежде чем найти рабочее решение поставленной проблемы. Поэтому хочу поделиться с вами тем, что в итоге у меня получилось. Ниже привожу фрагменты кода с ключевыми моментами.
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
//нужно, чтобы загружалась полная версия сайта, а не мобильная
webView.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"); 
webView.setWebViewClient(new WebViewClient()    
{
    @Override
    public void onPageFinished(WebView view, String url)
    {
        webView.loadUrl("javascript:window.HTMLOUT.processHTML('<html>'+"
        + "document.getElementsByTagName('html')[0].innerHTML+'</html>');");
    }

    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
    {
        super.onReceivedError(view, errorCode, description, failingUrl);
    }

	@Override
    public boolean shouldOverrideUrlLoading(WebView view, String url)
    {
        view.loadUrl(url);
        return true;
    }
});

private class MyJavaScriptInterface
{
    @JavascriptInterface
    public void processHTML(String html)
    {
        onPostExecute(html); 
        webView.stopLoading();
    }
}

public void execute()
{
    webView.loadUrl(url + urlQuery);
}
Методы execute и onPostExecute названы так, чтобы с получившимся классом можно было работать также как и с AsyncTask. Логика кода выше такая: браузер сообщает нам, что закончил свои дела по загрузке в событии onPageFinished, но теперь нам надо забрать исходный код страницы из браузера. Для этого прикручиваем JavaScriptInterface также как в коде выше. На stackoverflow.com находились различные вариации реализации этой хитрости, но почти ни один пример не работал. В каких-то тайных уголках гугла удалось найти решение и реализовать его, вот теперь делюсь хитрым приёмом с вами)

Теги , , ,
Автор