【问题标题】:Error in parsing HTML table and converting to JSON解析 HTML 表格并转换为 JSON 时出错
【发布时间】:2017-03-22 06:52:16
【问题描述】:
doc = Jsoup.parse("<table><tr><td>Phone No</td><td>Officers</td></tr><tr><td>123456789</td><td>Csa</td></tr></table>");
try {
    for (Element table : doc.select("table")) {
        for (Element row : table.select("tr")) {
            Elements tds = row.select("td");
            String PhoneNo = tds.get(0).text();
            String Officers = tds.get(1).text();
            jsonObject.put("Phone No", PhoneNo);
            jsonObject.put("Officers", Officers);
        }
        list.put(jsonObject);
    }
} catch ( JSONException e) {
    e.printStackTrace();
}

这段代码完美运行,但是当我尝试以下代码时

doc = Jsoup.connect(url).get();

它抛出NetworkOnMainThreadException,然后我遵循以下解决方案“Parsing with jsoup throws error (NetworkOnMainThreadException)”并将我的代码放入AsyncTask它抛出java.lang.RuntimeException: An error occured while executing doInBackground()

这里是堆栈跟踪:

FATAL EXCEPTION: AsyncTask #1    Process: com.rams.amar.information, PID: 12076    java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:304)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
    at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
    at java.util.ArrayList.get(ArrayList.java:308)
    at com.rams.amar.information.activities.ContactsActivity$MyTask.doInBackground(ContactsActivity.java:58)
    at com.rams.amar.information.activities.ContactsActivity$MyTask.doInBackground(ContactsActivity.java:41)
    at android.os.AsyncTask$2.call(AsyncTask.java:292)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
    at java.lang.Thread.run(Thread.java:818) 

这里是完整的代码:ContactsActivity.java

package com.rams.a.information.activities;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.TextView;
import com.rams.a.information.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;

public class ContactsActivity extends AppCompatActivity {
    String url="http://www.uok.ac.in/contactus.html";

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nav_contacts);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        this.setTitle("Contacts");
        MyTask mT = new MyTask();
        mT.execute();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        if((item.getItemId() == android.R.id.home))
        {
            onBackPressed();
        }
        return super.onOptionsItemSelected(item);
    }

    private class MyTask extends AsyncTask<Void, Void, String> {
        Document doc;
        JSONObject jsonObject = new JSONObject();
        JSONArray list = new JSONArray();

        @Override
        protected String doInBackground(Void... params) {
            try {
                doc = Jsoup.connect(url).get();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                for (Element table : doc.select("table")) {
                    for (Element row : table.select("tr")) {
                        Elements tds = row.select("td");
                        String PhoneNo = tds.get(0).text();
                        String Officers = tds.get(1).text();
                        jsonObject.put("Phone No", PhoneNo);
                        jsonObject.put("Officers", Officers);
                    }
                    list.put(jsonObject);
                }
            } catch ( JSONException e) {
                e.printStackTrace();
            }
            return list.toString();//stringArray.toString();
        }

        @Override
        protected void onPostExecute(String result) {

                ((TextView)findViewById (R.id.textView3)).setText(result);
        }
    }
}

【问题讨论】:

  • “发生错误”?什么错误? Stacktrace,好吗?
  • @cricjet_007 立即查看
  • 好的,IndexOutOfBoundsException 的哪一部分不清楚?如果tds.size() == 1,那么tds.get(1) 将永远无法工作
  • 我没有把它放在任何数组中,而是试图只显示在 TextView 中,正如我已经告诉上面的代码完美地工作并显示 JSON 数组 @cricjet_007
  • 好吧,就像我之前说的...tds.get(1) 会在tds.size() == 1 时出错。你可以调试你自己的代码看看doc.select("table")可能并不总是有两列的表。

标签: java android json android-asynctask jsoup


【解决方案1】:

看起来您的 HTML 表格数据并不总是有两列。

尝试添加 if 语句。

for (Element table : doc.select("table")) {
    for (Element row : table.select("tr")) {
        Elements tds = row.select("td");
        JSONObject jsonObject = new JSONObject();

        if (tds.size() >= 2) {  // see here                
            jsonObject.put("Phone No", tds.get(0).text());
            jsonObject.put("Officers", tds.get(1).text());

            list.put(jsonObject);
        }
    }
}

【讨论】:

  • 顺便说一下,您需要在循环中创建new JSONObject
  • 是的,它生成但它跳过了一个“电话号码”,即有人拿着两个数字
【解决方案2】:

请检查表格正文之前的内容中是否有任何附加标签,如 doctype 或 xml 声明等。

【讨论】:

    【解决方案3】:
    try {
         for (Element table : doc.select("table")) {
             for (Element row : table.select("tr")) {
                 JSONObject jsonObject = new JSONObject();
                 Elements tds = row.select("td");
                 if(tds.size()==1){continue;} else{
                     String PhoneNo = tds.get(0).text();
                     String Officers = tds.get(1).text();
                     jsonObject.put("Phone No", PhoneNo);
                     jsonObject.put("Officers", Officers);
                 }
                 list.put(jsonObject);
             }
         }
    } catch ( JSONException e) {
         e.printStackTrace();
    }
    

    此代码完美运行。

    【讨论】:

    • 如果我使用 if(tds.size()==1){ } 在列表中插入一个空行而不是跳过 if(tds.size()==1){continue;} 工作的记录,它会为整个列表和我身边的另一件事生成相同的数据。但是你给了我基本的想法,我真的很感激:)
    【解决方案4】:

    在您的活动 onCreate() 中写下以下代码

      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
      StrictMode.setThreadPolicy(policy);
    

    【讨论】:

    • 仅仅因为你能做到这一点并不意味着你永远应该这样做。
    猜你喜欢
    • 1970-01-01
    • 2017-05-05
    • 2016-12-18
    • 2015-09-02
    • 2013-07-02
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多