Страницы

Поиск по вопросам

воскресенье, 1 декабря 2019 г.

Парсинг сайта в java с помощью jsoup

#java #парсер #jsoup


Решил написать простенькую телепрограмму  с использованием jsoup. Задача более чем
скучная, но для меня новая ибо раньше с парсерами не работал. Прошу у Вас помощи не
в написание кода, а  совета как работать с парсером, читал статьи, но они рассказывают
только про заголовки  и т.п., а вот как например спарсить расписание с первого канала
на странице. И может быть вы считаете, что jsoup полная лажа посоветуйте другой.  
    


Ответы

Ответ 1



Ну, а в чём проблема? Загрузите документ. Снавигируйте к элементу, содержащему программы. Тем же способом найдите нужные элементы данных. Какие именно HTML-атрибуты вам нужны, устанавливается внимательным чтением исходника сайта, который вы собираетесь распарсить. На сайте даже есть простейший пример (без навигации, просто все ссылки).

Ответ 2



Есть 2 типа html/xml парсеров: SAX парсер - парсит в потоковом режиме, на вход подается поток html/xml, в определенных местах срабатывают т.н. хэндлеры, то есть перехватчики, которые говорят "сейчас парсер наткнулся на такой-то элемент". В хэндлер обычно прогер вставляет свой код и делает свое дело DOM парсер - засовывается весь источник, на выходе получаем дерево - иногда довольно сложное. jsoup это разновидность DOM парсера, так что весь вопрос в том, чтобы правильно спозиционироваться в дереве полученном после парсинга - или выражаясь языком модели DOM в нодах. Это описываетс документацией jsoup API в пакете org.jsoup.nodes. Заодно нелишним будет почитать про DOM это сразу направит мозги в нужном направлении. Удачи.

Ответ 3



Я это делаю так. Тоже первый раз :) Пока не разобрался как красиво выводить то, что спарсил :( package sm.play.sportlife.ua; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = MainActivity.class.getSimpleName(); public static int dayOfTheWeek = 0; // благодоря этому классу мы будет разбирать данные на куски public Elements time, currentday; // то в чем будем хранить данные public ArrayList timeList = new ArrayList(); public ArrayList dayEventList = new ArrayList(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** Запрос к нашему отдельному поток на выборку данных */ new GetDataThread().execute(); dayOfTheWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) - 1; if (dayOfTheWeek == 0) { dayOfTheWeek = 7; } Log.d(TAG, "День недели :" + dayOfTheWeek); } /** * А вот и внутрений класс который делает запросы в отдельном потоке */ public class GetDataThread extends AsyncTask { private TableRow row; private TableLayout inflate; private TextView txtcol1, txtcol2; private String eventNames; // private ProgressDialog prog; /** * Метод выполняющий запрос в фоне, в версиях выше 4 андроида, запросы в * главном потоке выполнять нельзя, поэтому все что вам нужно выполнять * - выносите в отдельный поток */ @Override protected String doInBackground(String... arg) { String myURL = "http://www.sportlife.ua/ru/services/schedule/14875"; // класс который захватывает страницу Document doc; try { // определяем откуда будем скачивать данные doc = Jsoup .connect(myURL) .userAgent( "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36") .get(); // задаем с какого места парсить /** * Выбираем содержимое рассписания по индексу столбца * td:eq(Индекс) */ // Время занятий int k = 0; String link = "#shedule-content tr:gt(0) " + "td:eq(" + k + ")"; time = doc.select(link); link = "#shedule-content tr:gt(0) " + "td:eq(" + dayOfTheWeek + ")"; currentday = doc.select(link); /** * Чистим наши ArrayList для того что бы заполнить и в цикле * захватываем все данные какие есть на странице */ timeList.clear(); dayEventList.clear(); for (Element times : time) { if (times.className().equals("time-col")) { timeList.add(times.text()); // Записываем в ArrayList // время занятий } } /** * Для каждого event currentday из записываем в аррей лист * события дня */ for (Element event : currentday) { if (event.hasText() == true) { Elements mEvents = Jsoup.parse(event.html()).select( ".event-item-body"); /** Может быть несколько занятий на одно и тоже время */ int i = 0; do { Element textEvent = mEvents.get(i); String tmpString = textEvent.text(); if (eventNames == null) { eventNames = tmpString + "\n"; } else { eventNames = eventNames + tmpString + "\n"; } i++; } while (i < mEvents.size()); /** События заносим в список */ dayEventList.add(eventNames); eventNames = ""; } else // dayEventList.add(titles.text()); dayEventList.add(""); } } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPreExecute() { // prog = new ProgressDialog(MainActivity.this); // prog.setMessage("Соединяемся..."); // prog.show(); } @Override protected void onPostExecute(String result) { /** ФОРМИРУЕМ ТАБЛИЦУ */ inflate = (TableLayout) MainActivity.this .findViewById(R.id.mytable); for (int i = 0, j = 0; i < timeList.size() || j < dayEventList.size();) { row = new TableRow(MainActivity.this); txtcol1 = new TextView(MainActivity.this); if (timeList.size() > i) { if ((timeList.get(i) != null)) { txtcol1.setText(timeList.get(i)); txtcol1.setBackgroundResource(R.drawable.shape_rec); // txtcol1.setTextColor(Color.rgb(245, 245, 220)); // txtcol1.setBackgroundColor(Color.rgb(0, 0, 0)); i++; } } else { txtcol1.setText(""); } row.addView(txtcol1); txtcol2 = new TextView(MainActivity.this); if ((dayEventList.size() > j)) { if (dayEventList.get(j) != null) { txtcol2.setText(dayEventList.get(j)); txtcol2.setBackgroundResource(R.drawable.shape_rec); // txtcol2.setMaxLines(20); j++; } } else { txtcol2.setText(""); } this.row.addView(txtcol2); inflate.addView(row); } /** КОНЕЦ ФОРМИРОВАНИЯ ТАБЛИЦЫ */ // super.onPostExecute(result); // prog.dismiss(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } } }

Комментариев нет:

Отправить комментарий