android - Нужна помощь в парсинге URL mp3 файлов через Jsoup


2

Я пытаюсь разобрать эту страницу через jsoup и получить ArrayList прямых ссылок на mp3 файлы глав книги, но что бы я не пробовал у меня не выходит.

Ссылка

Отдельный элемент

<div class="jp-free-media" style="font-size:xx-small;">(<a id="jp_playlist_1_item_0_mp3" href="https://qa-help.ru/go/go_redirect?url=http%3A%2F%2Fwww.archive.org%2Fdownload%2Fhuckleberry_mfs_librivox%2Fhuckleberry_finn_01_twain_64kb.mp3" tabindex="1">download</a>)</div>

Мой класс AsyncTask, строки пытаюсь получить в mLines2:

public class FillBook extends AsyncTask<Void, Void, List<String>> {

    //site url to be passed into consructor
    private String link;
    private String imgLink;
    private String title;
    String description;
    private List<String> tmpChapters = new ArrayList<>();
    private List<SingleBook> books = new ArrayList<>();

    public FillBook(String link, String imgLink, String title) {

        this.link = link;
        this.imgLink = imgLink;
        this.title = title;
    }

    @Override
    protected List<String> doInBackground(Void... params) {

        //parsed doc will be stored in this field
        Document doc = null;

        //fields to store raw html lines used to extract book names, their thumbnails
        // as well as number of total pages of the books category
        Elements mLines;

        try {
            //connect to the site
            doc = Jsoup.connect(link).get();

        } catch (IOException | RuntimeException e) {
            e.printStackTrace();
        }
        if (doc != null) {

            // getting all elements with classname "layout"
            mLines = doc.getElementsByClass("book-description");

            //searching for book names and their thumbnails and adding them to ArrayLists
            for (Element mLine : mLines) {
                description = mLine.text();
            }

            String arr = "";
            String html = doc.body().html();
            if (html.contains("var audioPlaylist = new Playlist("1", ["))
                arr = html.split("var audioPlaylist = new Playlist("1", [")[1];
            if (arr.contains("]"))
                arr = arr.split("]")[0];
            Log.d(LOG_TAG, "ARRAY! " + arr);
            //-----------------------------------------
            if (arr.contains("}") && arr.contains("{")) {
                Log.d(LOG_TAG, "wierd");
                for (String mLine2 : arr.split("},{")) {
                    if (mLine2.contains("mp3:"")) {
                        tmpChapters.add(mLine2.split("mp3:"")[1].split(""")[0]);
                    }
                }
            } else if (arr.contains("mp3:""))
                Log.d(LOG_TAG, "something whrong");
                tmpChapters.add(arr.split("mp3:"")[1].split(""")[0]);
        }else
            System.out.println("ERROR");

        Log.d(LOG_TAG, "SIZE_OF_tmpChapters" + tmpChapters.size());
        return tmpChapters;

    }

    protected void onPostExecute(List<String> tmpChapters) {
        super.onPostExecute(tmpChapters);
        Toast.makeText(BookActivity.this, "size "+ tmpChapters.size(), Toast.LENGTH_SHORT).show();

        if (tmpChapters.size() > 0) {
            try {
                Picasso.get().load(imgLink).into(bookCover);
                nameAndAuthor.setText(title);
                bookDescription.setText(description);
                for (int i = 0; i < tmpChapters.size(); i++) {
                    books.add(new SingleBook(tmpChapters.get(i)));
                }
                if (listChapters.getAdapter() != null) {
                    adapter.clear();
                    adapter.addAll(books);
                } else {
                    adapter = new CustomAdaterChapters(BookActivity.this,
                            R.layout.book_chapters_listview_item, books);
                    listChapters.setAdapter(adapter);

                }
                listChapters.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                        String link = adapter.getChapters(position);
                        playbackIntent = new Intent(BookActivity.this, PlayerService.class);
                        startService(playbackIntent.putExtra("link", link));
                    }
                });

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

        } else Toast.makeText(BookActivity.this, "NETWORK ERROR", Toast.LENGTH_LONG).show();

    }
}

В итоге получаю пустой ArrayList. Посоветуйте, пожалуйста, как запросить с учетом того, что следующая глава будет соответственно id="jp_playlist_1_item_1_mp3" и так далее.

Источник
  •  115
  •  1
  • 30 янв 2018 2018-01-30 18:14:17

1 ответ

3

Дело в том что в html коде нет данного класса, он создается с помощью js Если сделать запрос и посмотреть html, то можно увидеть след. введите сюда описание изображения

Попробуйте с помощью jsoup достать html body а потом с помощью регулярки или обычным split вырезать данный массив. Если вырезать через сплит - не забудьте делать проверку. Например

String arr = "";
String html = data.body().html();
if (html.contains("var audioPlaylist = new Playlist("1", ["))
   arr = html.split("var audioPlaylist = new Playlist("1", [")[1];
if (arr.contains("]"))
   arr = arr.split("]")[0];

в вашем случаи функция будет выглядеть так

@Override
protected SingleBook doInBackground(Void... params) {

    Document doc = null;
    book = new SingleBook(imgLink, title, false, false, null, new ArrayList<String>());


    Elements mLines;

    try {
        doc = Jsoup.connect(link).get();

    } catch (IOException | RuntimeException e) {
        e.printStackTrace();
    }
    if (doc != null) {


        mLines = doc.getElementsByClass("book-description");


        for (Element mLine : mLines) {
            String description= mLine.text();
            book.setDescription(description);

        }


        //Лучше вместо split использовать регулярки, но я их плохо знаю
        String arr = "";
        String html = doc.body().html();
        if (html.contains("var audioPlaylist = new Playlist("1", ["))
            arr = html.split("var audioPlaylist = new Playlist("1", [")[1];
        if (arr.contains("]"))
            arr = arr.split("]")[0];
        //-----------------------------------------
        if (arr.contains("},")) {
            for (String mLine2 : arr.split("},")) {
                if (mLine2.contains("mp3:""))
                    tmpChapters.add(mLine2.split("mp3:"")[1].split(""")[0]);
            }
        } else if (arr.contains("mp3:""))
            tmpChapters.add(arr.split("mp3:"")[1].split(""")[0]);
    }else
        System.out.println("ERROR");

    book.setChapters(tmpChapters);
    return book;
}
  • 31 янв 2018 2018-01-31 15:09:28
Так в коде выше ничего не поменялось, последнее редактирование 21 декабря :) Может вы сохранить забыли... Я обрезал пробелы, как вы сказали, я на них и думал, но как это сделать не сообразил :) Теперь в ArrayList попадают все записи, но помимо этого следом еще раз добавляется 1 запись. Условие else if (arr.contains("mp3:"")) не выполняется вообще. — 29 янв 20182018-01-29 09:50:52.000000
во первых так делать не надо if (arr.contains("}") && arr.contains("{")) нужно делать проверку именно на то что мы режем - arr.split("},{"). Попробуйте перед if (arr.contains("}") && arr.contains("{")) убрать пробелы arr=arr.replace(" ","").replace("n","").replace("r","").trim(); или сделать как я обновил в коде — 29 янв 20182018-01-29 09:50:52.000000
Я доделал код выше, сейчас async выглядит так, но ваш код я не трогал и несколько раз его отсюда в студию вставлял. Не работает и по той ссылке, которая в вопросе, и по другим тоже, но до этого работало везде. Сейчас массив получается размером 1 элемент - там только первая ссылка из списка, и выполняется только else условие. Я более-менее понял, что вы делаете в коде, и мне кажется, что там вроде все правильно, но оно не работает. Может на сайте что то поменялось... не знаю, что думать. — 29 янв 20182018-01-29 09:50:52.000000
Чуть по подробней, где то ошибку выдает? Не работает именно на той ссылке что была в вопросе? — 29 янв 20182018-01-29 09:50:52.000000
Извините, что опять беспокою, но код перестал работать, но я его не трогал вроде, можете помочь? — 29 янв 20182018-01-29 09:50:52.000000