пятница, 29 ноября 2013 г.

Парсинг сайта в Android

Сегодня я хочу вам рассказать как быстро и без усилий спарсить любой сайт, а точнее любые данные с сайта при помощи библиотеки jsoup. Статья будет оочень не большая так как у этой библиотеки в принципе очень хороший функционал состоящий из двух классов, это Document — который захватывает нужную страницу, и Element — захватывает нужный элемент. Вот собственно и все. 

На главном сайте этой библиотеки есть пример работы, но не каждый будет читать что та написано, поэтому я решил что я напишу у себя как это сделать, заодно заметка будет что бы не забыть на будущее (:.



В общем все как по старинке, запускаем Eclipse, создаем проект. Значит парсить мы будем freehabr.ru, стырим у них название поста чисто для примера.

И так для начала скачивайте библиотеку с сайта jsoup.org, дальше добавляйте ее в папку libs/ которая есть в вашем проекте. 

Дальше открывайте файл MainActivity.java или как он там у вас называется и удаляем все. Наша программа будет состоять из двух классов, первый будет у нас главным, это собственно наш MainActivity, а второй будет внутренний, который будет выполнять запросы на сайт который мы хотим парсить, в нем будет происходит парсинг и разбор данных.

Давайте я привелу код нашего класса с комментариями, я думаю там будет все понятно.

MainActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends Activity {

        // благодоря этому классу мы будет разбирать данные на куски
        public Elements title;
        // то в чем будем хранить данные пока не передадим адаптеру
        public ArrayList<String> titleList = new ArrayList<String>();
        // Listview Adapter для вывода данных
        private ArrayAdapter<String> adapter;
        // List view
        private ListView lv;

        @Override
        protected void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                // определение данных
                lv = (ListView) findViewById(R.id.listView1);
                // запрос к нашему отдельному поток на выборку данных
                new NewThread().execute();
                // Добавляем данные для ListView
                adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.product_name, titleList);
        }

        /** А вот и внутрений класс который делает запросы, если вы не читали статьи у меня в блоге про отдельные
         * потоки советую почитать */
        public class NewThread extends AsyncTask<String, Void, String> {

                // Метод выполняющий запрос в фоне, в версиях выше 4 андроида, запросы в главном потоке выполнять
                // нельзя, поэтому все что вам нужно выполнять - выносите в отдельный тред
                @Override
                protected String doInBackground(String... arg) {

                        // класс который захватывает страницу
                        Document doc;
                        try {
                                // определяем откуда будем воровать данные
                                doc = Jsoup.connect("http://freehabr.ru/").get();
                                // задаем с какого места, я выбрал заголовке статей
                                title = doc.select(".title");
                                // чистим наш аррей лист для того что бы заполнить
                                titleList.clear();
                                // и в цикле захватываем все данные какие есть на странице
                                for (Element titles : title) {
                                        // записываем в аррей лист
                                        titleList.add(titles.text());
                                }
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                        // ничего не возвращаем потому что я так захотел)
                        return null;
                }

                @Override
                protected void onPostExecute(String result) {

                        // после запроса обновляем листвью
                        lv.setAdapter(adapter);
                }
        }
}


Из комментариев ясно что и как тут работает, надеюсь. 

Далее нам нужно создать разметку, она у нас будет простая, всего лишь один листвью в который мы будем выводить весь текст который спарсим.

main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >
    </ListView>
</RelativeLayout>


И нам нужно не забыть добавить разрешение приложению выходить в интернет для этого нам нужно прописать в AndroidManifest.xml две строки чуть выше <aplication>:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>


Все теперь все должно работать и при запуске приложения вы должны видеть примерно вот такую картинку.


Скачать исходники:

1 комментарий: