1

概要: 私の Jsoup パーサーは単独では完全に機能しますが、Android アプリケーションの AsyncTask タスク クラスの 1 つにコピー アンド ペーストすると値を収集できません。2 次元配列は null だけで埋められて返されます。

長いバージョン: 私は、Jsoup を介してページ スクレイピングを使用して、さまざまなブログからコンテンツをプルして表示するアプリケーションに取り組んできました。これまでにいくつかのパーサーを作成しましたが、すべて期待どおりに動作するようです。残念ながら、私の最新のパーサー (nyc-shows.brooklynvegan.com 用に作成) には問題がありました。

これは、print ステートメントが追加されたメイン メソッドによって呼び出されるパーサー メソッド自体です。これを自分で実行します。それは機能します(完全ではありませんが、機能します)。

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Main {

    static String TAG_EVENT = "li.ds-entry";
    static String TAG_TITLE = ".ds-entry-title";
    static String TAG_LOCATION = ".location";
    static String TAG_DATE_AND_TIME = ".ds-date";
    static String TAG_TICKET_URL = ".ds-buy-tickets";
    static String FEED_URL = "http://nyc-shows.brooklynvegan.com/";

    public static void main(String[] args) throws IOException {
    String values[][] = new String[50][6];
    values = getFeedItems();
    for (int i=0; i<values.length; i++) {
        for (int j=0; j<6; j++) {
        System.out.println(values[i][j]);
        }
    System.out.println("-----------------");
    }
    }


    public static String[][] getFeedItems() throws IOException {

    Document doc = null;
    String values[][] = new String[50][6];


    try{
        doc = Jsoup.connect(FEED_URL).timeout(0).get();
        Elements events = doc.select(TAG_EVENT);

        String delimSpace = "[ ]";
        int i = 0;
        for (Element event : events) {


        //Set event title
        Element title = event.select(TAG_TITLE).first();
        String titleString = title.text();
        if (title != null) {
            boolean isFake = checkFake(titleString);
            if (!isFake) {
            values[i][0] = titleString;
            }
            else {
            continue;
            }
        }

        //Set event date and time i guess
        Element dateAndTime = event.select(TAG_DATE_AND_TIME).first();
        if (dateAndTime != null) {
            String[] dateAndTimeTokens = dateAndTime.text().split(delimSpace);
            String date = dateAndTimeTokens[1];
            String time = dateAndTimeTokens[3];
            values[i][1] = date;
            values[i][2] = time;
        }

        //Set price (tbd)
        values[i][3] = "See Ticket";

        //Set location
        Element location = event.select(TAG_LOCATION).first();
        if (location != null) {
            values[i][4] = location.text();
        }

        //Set ticket urls
        Element ticketContainer = event.select(TAG_TICKET_URL).first();
        if (ticketContainer != null) {
            String ticket = ticketContainer.select("a").attr("href");
            values[i][5] = ticket;
        }
        else {
            values[i][3] = "Free";
        }

        i++;
        } //End of event loop
    } //End of try clause

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

    return values;
    }


    public static boolean checkFake(String s) {
    boolean isFake = false;
    String[] days = {"Today", "Tomorrow", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    for (int i=0; i<days.length; i++) {
        if (s.contains(days[i])) {
        isFake = true;
        return isFake;
        }
    }
    return isFake;

     }
}

ここで、ロード画面が表示されている間にアプリケーションによってバックグラウンドで実行されるように、AsyncTask に転送されたのとまったく同じメソッドを次に示します。

package com.example.nylist;

import java.io.IOException;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class BVParser extends AsyncTask<Void, Void, String[][]> {
    static String TAG_EVENT = "li.ds-entry";
    static String TAG_TITLE = ".ds-entry-title";
    static String TAG_LOCATION = ".location";
    static String TAG_DATE_AND_TIME = ".ds-date";
    static String TAG_TICKET_URL = ".ds-buy-tickets";
    static String FEED_URL = "http://nyc-shows.brooklynvegan.com/";
    Context context;
    Activity activity;

    public BVParser(Activity context) {
    this.context = context.getApplicationContext();
    this.activity = context;
    } 



    @Override
    protected void onPreExecute() {
       super.onPreExecute();
       Toast.makeText(context, "Fetching...", Toast.LENGTH_LONG).show();
    }

    @Override
    protected String[][] doInBackground(Void... param) {
    String values[][] = new String[50][6];
    try {
        values = getFeedItems();
    } 
    catch (IOException e) {
        Log.d("ASSERT", "Exception occured during doInBackground", e);
        e.printStackTrace();
    }

    Log.d("ASSERT", ("values successfully returned by doInBackground, first title is: "+values[0][0]));
    return values;
    }

    protected void onPostExecute(String[][] result) {
    super.onPostExecute(result);
    int eventCount = result.length;
    Log.d("ASSERT", ("event count in onPostExecute is: "+eventCount));
    ListRow[] listrow_data = new ListRow[eventCount];
    ListRow temp;
    for (int i=0; i<eventCount; i++) {
        if (result[i] != null) {
        temp = new ListRow(context, result[i][0], result[i][1], result[i][2], 
            result[i][3], result[i][4], result[i][5], i);
        listrow_data[i] = temp;
        }
    }
    ((EventList) activity).setList(listrow_data);    
    }


    public String[][] getFeedItems() throws IOException {

    Document doc = null;
    String values[][] = new String[50][6];
    int i = 0;

    try{
        Log.d("ASSERT","Made it to try block");
        doc = Jsoup.connect(FEED_URL).timeout(0).get();
        Elements events = doc.select(TAG_EVENT);
        Log.d("ASSERT","printing events, whatever it is: "+events);

        String delimSpace = "[ ]";

        //******THIS LOOP NEVER BEGINS*****//
        for (Element event : events) {
        Log.d("ASSERT","Made it to getFeedItems's main for loop");

        //Set event title
        Element title = event.select(TAG_TITLE).first();
        String titleString = title.text();
        Log.d("ASSERT","This title is: "+titleString);
            boolean isFake = checkFake(titleString);
            if (!isFake) {
            values[i][0] = titleString;
            }
            else {
            continue;
        }

        //Set event date and time i guess
        Element dateAndTime = event.select(TAG_DATE_AND_TIME).first();
        if (dateAndTime != null) {
            String[] dateAndTimeTokens = dateAndTime.text().split(delimSpace);
            String date = dateAndTimeTokens[1];
            String time = dateAndTimeTokens[3];
            values[i][1] = date;
            values[i][2] = time;
        }

        //Set price
        values[i][3] = "See Ticket";

        //Set location
        Element location = event.select(TAG_LOCATION).first();
        if (location != null) {
            values[i][4] = location.text();
        }

        //Set ticket urls
        Element ticketContainer = event.select(TAG_TICKET_URL).first();
        if (ticketContainer != null) {
            String ticket = ticketContainer.select("a").attr("href");
            values[i][5] = ticket;
        }
        else {
            values[i][3] = "Free";
        }

        i++;
        } //End of event loop
    } //End of try clause

    catch (IOException e) {
        Log.d("ASSERT","Exception during getFeedItems");
        e.printStackTrace();
    }
    Log.d("ASSERT","The first title in getFeedItems before returning is: "+values[0][0]);
    return values;
    }


    private static boolean checkFake(String s) {
    boolean isFake = false;
    String[] days = {"Today", "Tomorrow", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    for (int i=0; i<days.length; i++) {
        if (s.contains(days[i])) {
        isFake = true;
        return isFake;
        }
    }
    return isFake;

    }

}

デバッグの試み: 問題をデバッグするために、コード全体にログ ステートメントを追加しました。これを実行すると、getFeedItems() 自体のどこか、特に「try」ブロック内で問題が発生しているように見えることがわかります。try ステートメントの先頭にログ ステートメントが表示されますが、実行される for ループeventsはまったく実行されません。これは、最初のログ ステートメントが出力されないためです。

質問:eventsループ スルーが始まらない 理由を誰か説明できますか? eventsnull である場合、その理由は? それ自体で実行されているメソッドと AsyncTask 内で実行されているメソッドとの間に矛盾があるのはなぜですか? 私は髪をかきむしってきました。このパーサーのロジックは、私が書いた (動作中の) 他のパーサーのロジックとほとんど同じですが、これは null しかない 2 次元配列を返しています。論理エラーがどこにあるかを理解するのに苦労していますが、タイプミスを見つけることができないようです.

PS: これを私の他のパーサーと比較すると役立つ場合は、お知らせください。ソースを投稿します。前もって感謝します。

4

0 に答える 0