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
- Alex Medentsov
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
- Tiarait
Так в коде выше ничего не поменялось, последнее редактирование 21 декабря :) Может вы сохранить забыли... Я обрезал пробелы, как вы сказали, я на них и думал, но как это сделать не сообразил :) Теперь в ArrayList попадают все записи, но помимо этого следом еще раз добавляется 1 запись. Условие else if (arr.contains("mp3:"")) не выполняется вообще. — Alex Medentsov 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(); или сделать как я обновил в коде — Tiarait 29 янв 20182018-01-29 09:50:52.000000
Я доделал код выше, сейчас async выглядит так, но ваш код я не трогал и несколько раз его отсюда в студию вставлял. Не работает и по той ссылке, которая в вопросе, и по другим тоже, но до этого работало везде. Сейчас массив получается размером 1 элемент - там только первая ссылка из списка, и выполняется только else условие. Я более-менее понял, что вы делаете в коде, и мне кажется, что там вроде все правильно, но оно не работает. Может на сайте что то поменялось... не знаю, что думать. — Alex Medentsov 29 янв 20182018-01-29 09:50:52.000000
Чуть по подробней, где то ошибку выдает? Не работает именно на той ссылке что была в вопросе? — Tiarait 29 янв 20182018-01-29 09:50:52.000000
Извините, что опять беспокою, но код перестал работать, но я его не трогал вроде, можете помочь? — Alex Medentsov 29 янв 20182018-01-29 09:50:52.000000