Страница 1 из 2

Jsoup parsing

Добавлено: 19 июн 2012, 13:41
Xpert043
Вопрос по библиотеке Jsoup. (оф сайт: http://jsoup.org)
Смог по (http://developer.alexanderklimov.ru/and ... php#common) этому уроку прочитать заголовок страницы из интернета. Теперь у меня есть сайт с кучей CSS кодов (a hreg, center и т.д.). Надо выделить определенную часть текста. Если кто работал с CSS-селектором библиотеки Jsoup, отпишитесь сюда.
Вот пример с официального сайта:

Код: Выделить всё

File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Elements links = doc.select("a[href]"); // a with href
Elements pngs = doc.select("img[src$=.png]");
  // img with src ending .png

Element masthead = doc.select("div.masthead").first();
  // div with class=masthead

Elements resultLinks = doc.select("h3.r > a"); // direct a after h3
Еще интересует дальнейший вывод списка в Listview.
Жду советов. А пока буду сам разбираться и если найду решение-напишу.

Re: Jsoup parsing

Добавлено: 19 июн 2012, 14:58
Xpert043
Вот еще что нашел(источник: http://www.codeproject.com/Articles/209 ... -using-CSS):

Код: Выделить всё

 try {
            File input = new File("input/dZoneLinks.xml");
            Document doc = Jsoup.parse(input, "UTF-8",
                    "http://www.dzone.com/links/?type=html&p=2");

            Elements descriptions = doc.select("div.details > p.description");
            // get all description elements in this HTML file
            for (Element element : descriptions) {
                System.out.println(element.ownText());
                System.out.println("--------------");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
Теперь надо разобраться как это вывести в TextView...

Re: Jsoup parsing

Добавлено: 19 июн 2012, 15:16
Xpert043
Вот еще меньший "кусочек" программы:

Код: Выделить всё

Document doc = null;
		try {
            File input = new File("input/FILE.xml");
            doc = Jsoup.parse(input, "UTF-8","http://www.dzone.com/links/?type=html&p=2");
            Elements descriptions = doc.select("div.details > p.description");
       } catch (Exception e) {
            e.printStackTrace();
        }
		String linkHref = doc.attr("href"); 
		tvInfo.setText(linkHref); 
Вопрос: как выводить текст полученный в Elements? На main.xml имею только textview.

Re: Jsoup parsing

Добавлено: 19 июн 2012, 18:08
Prospekt
Я не работал с данной библиотекой, но
Не могли бы вы как-нибудь попонятней объяснить саму задачу и возникшие проблемы. Три раза читал, ничего не понял, совсем дурной однако я стал. :)

Re: Jsoup parsing

Добавлено: 19 июн 2012, 18:45
Xpert043
Есть какой нибудь вот такой код(исходный код страницы форума):
td id="ph-12977071-d2" class="row2" valign="middle" width="99%">
<!-- POSTED DATE DIV -->
<div style="float: left;">
<span class="postdetails"> <img src="http://s.4pda.ru/forum/style_images/1/to_post_off.gif" alt="" border="0" style="padding-bottom:2px" /> 03.05.2012, 20:24</span>
</div>
<!-- REPORT / DELETE / EDIT / QUOTE DIV -->
<div style="float:left;margin-left:50px;" id="kh-12977071"></div>
<div align="right">
<span class="postdetails">Сообщение <a title="Ссылка на это сообщение" href="/forum/index.php?showtopic=286021&view=findpost&p=12977071" onclick="link_to_post(12977071); return false;">#1</a></span>
</div>
</td>
Задача с помощью CSS-селекторов, которые поддерживаются библиотекой Jsoup извлечь элементы текста или ссылок. Выше в постах я выкладывал какие то примеры, которые находил в интернете. А Elements, это тот параметр, который выделяет кусочек текста с определенными тегами ("a href" "div" и другие). У меня задача в том, чтобы то что выделил Elements из общей кучи текста, вывести в TextView на моей форме.
Надеюсь понятно объяснил. Если все равно что то не понятно, спрашивайте.

Re: Jsoup parsing

Добавлено: 19 июн 2012, 19:41
Prospekt
И что не получается?
Предположим у вас на форме 3 ТехтВиев с соответствующими id "text_1","text_2", "text_3". Как я понял у вас форма фиксирована, т.е. у ней есть 3 элемента (ни 2, ни 4, а именно 3).
Elements содержит список распарсенных участков кода HTML. Как получать этот список вы привели сами.
Теперь чтобы первое значение записалось в "text_1" нужно что-то вроде:

Код: Выделить всё

Elements description;
for(int i=0; (i<description.size())&&(i<3); i++){
 TextView tv = findById("text_"+i);
 Element el = description.get(i);
 tv.setText(el.text);
}
Этой библиотеки под рукой нет, поэтому методы взятие элемента из списка и размера списка могут быть иными. Но в целом должно выглядеть как-то так. Данный код выводит текстовые значения первых трех элементов в соотвествующие TextView-ы.
Как я понимаю, если форма у вас имеет переменную длинну и формируется динамически, то вам придется хранить количество уже имеющихся ТехтВиев-ов на форме. Если это количество совпадает с длинной найденных элементов, то просто заменить у них текстовые значения. Если список длиннее добавить на форму недостающее количество, а если короче удалить лишнии элементы с формы.

Вы же собственно все сами и сделали, поэтому я не понимаю собственно в чем вопрос. В том как получить текст из Element (.text) и вставить его в TextView найденный через id? На каком этапе проблема, и в чем она?

Re: Jsoup parsing

Добавлено: 19 июн 2012, 20:35
Xpert043
Подробнее о библиотеке можно посмотреть на сайте http://jsoup.org. Сейчас попробую сделать то что ты описал.
А вот как теперь быть:

Код: Выделить всё

Document doc = null;
		try {
            File input = new File("input/FILE.xml");
            doc = Jsoup.parse(input, "UTF-8","http://www.dzone.com/links/?type=html&p=2");
            Elements descriptions = doc.select("div.details > p.description");
       } catch (Exception e) {
            e.printStackTrace();
        }
		
		Elements description;
		for (int i = 0; (i < description.size()) && (i < 3); i++) {
			TextView tv = findViewById("textView" + i);
			Element el = description.get(i);
			tv.setText(el.textView);
		}

Подчеркивает жирный элемент: "tv.setText(el.textView);"
"textView cannot be resolved or is not a field"

Может попробовать реализовать с помощью ListView (вместо textview)? Все таки раз Elements, значит их много (не один), значит выводить в цикле в список.

Re: Jsoup parsing

Добавлено: 19 июн 2012, 20:59
Prospekt
По ходу нужно не
tv.setText(el.textView); (такого поля у этого класса нет)
а
tv.setText(el.text()); если нужно получить текст вместе с вложенными тегами и телом
или tv.setText(el.ownText()); если нужно получить только текст этого элемента
ещё есть метод data() но что он выдает я не знаю.

СТОП!!!!
Я как-то упустил, что элементы выводятся в список. Я почему-то думал в форму, состоящую из ТехтВиев-ов. Или нет? чего-то я запутался.

10-я строка лишняя
Elements description(s); - это я чтобы было понятно, что есть что.

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:04
Xpert043
Я это недавно дописал. Изначально выводятся в textview но может так как элементов много, то стоит попробовать Listview? Вообще в будущем планируется пасить целый список, но я решил начать с легкого и выводить просто в textview

Ругается на "findById" и предлагает создать метод "findViewById". Но зачем его создавать, если там нечего описывать.
Вот код ошибки:
"The method findById(String) is undefined for the type"
Это означает, что метод полезен только для строк?
Убрал "Elements description" теперь пишет "description cannot be resolved"

Кстати вот еще интересно, почему после try {} catch {} типы указанные внутри них снаружи оказываются необъявленными....?

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:15
Xpert043

Код: Выделить всё

Document doc = null;
		try {
			doc = Jsoup.connect("http://yandex.ru")
					.get();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String title = doc.title();
		tvInfo.setText(title);
Вот как было раньше. И все он выводил. А с появлением Elements все испортилось...

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:18
Prospekt
Это я ошибку сделал.
Ругается на "findById" и предлагает создать метод "findViewById
Правильно советует. Я просто код не в IDE писал поэтому и пропустил часть слова.
прибавь к description на конец "s". Поля в 5-й и 10- строке это одно и тоже. Я просто описался. И вообще, внеси код под блок try{...} после 5-й строки.

Счас подожди.

Естественно не видит. Поле объявлено внутри блока будет иметь локальную область видимости, т.е. лоступно только внутри этого же блока. Чтобы сделать поле видимым, надо объявить его до блока, а уже в блоке присваивать значение.

замени на findViewById() я именно это и хотел написать.

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:20
Xpert043
Про description (s) уже исправлял, но когда он был за пределами try... все равно подчеркивал. Сейчас внес внутрь и подчеркивает только findbyid

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:27
Xpert043
Заменить строку на это: "TextView tv = findViewById("textView" + i);"?
Теперь ошибка такая: "The method findViewById(int) in the type Activity is not applicable for the arguments (String)"

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:29
Prospekt
ДА. Здесь мы выбираем тот ТекстВиев которому будем присваивать текст.
Блин, забыл, что кастомизацию (TextView) надо делать, вот оно побочное действие автоматизации.

Да уж. сегодня явно не мой день. Ну конечно, нельзя в аргумент передавать строку. Надо передавать int из R.id

Ладно в кчестве кастыля сделай так:

int[] idtext = new int[]{R.id.textView1 , R.id.textView2 , R.id.textView3 }; (где-нибудь вначале класса)

и

TextView tv = (TextView)findViewById(idtext);
Это конечно не красиво, но для опробывания сойдет.

Кастомизация - это приведение типов (от слова "cast").

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:40
Xpert043
Вот что в итоге получил:

Код: Выделить всё

int[] idtext = new int[]{R.id.textView1 , R.id.textView2 , R.id.textView3 };
		Document doc = null;
		try {
            File input = new File("input/FILE.xml");
            doc = Jsoup.parse(input, "UTF-8","http://www.dzone.com/links/?type=html&p=2");
            Elements descriptions = doc.select("div.details > p.description");
            for (int i = 0; (i < descriptions.size()) && (i < 3); i++) {
            	TextView tv = (TextView)findViewById(idtext[i]);
    			Element el = descriptions.get(i);
    			tv.setText(el.ownText());
    		}
       } catch (Exception e) {
            e.printStackTrace();
        }

Сейчас буду пробовать.
Странно, вывел мне только форму мою, с тремя разными textview. Наверно надо разбираться в коде парсера. Может сайт уже устарел, и его CSS код изменился...
А должен вывести что то вроде этого:
<p class="description">
In administrative systems, there is often a need to import and parse csv files. .NET actually has a built in CSV parser, although it is...&nbsp;
<a href='/links/built_in_net_csv_parser.html'>more&nbsp;&raquo;</a>

</p>"

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:45
Prospekt
А ты выведи в Log значение descriptions.size()

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:48
Xpert043
Стыдно спрашивать, но: "Log.d(descriptions.size());"...?

Отойду пока, вернусь к этому делу позже. Спасибо за помощь. Об успешном (надеюсь) исходе отпишусь:)

Re: Jsoup parsing

Добавлено: 19 июн 2012, 21:53
Prospekt
Ничего стыдного. Если ты работаешь в Эклипсе, то там наверное надо так
final String LOG_TAG = "myLogs";
Log.d(LOG_TAG, descriptions.size());

Чтобы легко можно было найти по логам\тегу

Re: Jsoup parsing

Добавлено: 19 июн 2012, 23:26
Xpert043
Сделал, теперь код вот такой:

Код: Выделить всё

int[] idtext = new int[]{R.id.textView1 , R.id.textView2 , R.id.textView3 };
		Document doc = null;
		try {
            File input = new File("input/FILE.xml");
            doc = Jsoup.parse(input, "UTF-8","http://www.dzone.com/links/?type=html&p=2");
            Elements descriptions = doc.select("div.details > p.description");
            for (int i = 0; (i < descriptions.size()) && (i < 3); i++) {
            	TextView tv = (TextView)findViewById(idtext[i]);
    			Element el = descriptions.get(i);
    			tv.setText(el.ownText());
                                  final String LOG_TAG = "myLogs"; 
                                  Log.d(LOG_TAG, descriptions.size());
    		}
       } catch (Exception e) {
            e.printStackTrace();
        }
Подчеркивает Log.d
Ошибка: "The method d(String, String) in the type Log is not applicable for the arguments (String, int)"

Re: Jsoup parsing

Добавлено: 20 июн 2012, 07:34
Prospekt
Блин,
Замени на
Log.d(LOG_TAG, ""+descriptions.size());
Или более правильный вариант
Log.d(LOG_TAG, Integer.toString( descriptions.size()));