哈勃!
亲爱的读者! 如果您对html解析和Android开发感兴趣,那么本文适合您。 希望您在其中找到许多有趣且有用的东西。 我想在其中分享我在该领域的经验。
问题描述
关于我的一点。 我是ITA SFU的三年级学生。 像所有学生一样,我需要每天查看课程表。 而且我不仅需要知道第二天的时间表,还需要提前一两周知道时间表。
看来,为什么不保存时间表并使用它呢? 不幸的是,有许多原因阻止了这种情况,即:
- 一个星期的时间表可能与另一个星期的时间表截然不同
- 日程安排不固定,可能会改变
当然,有一个有时间表的站点,但这不是很方便,因为它只显示带有时间表的原始表,为期20周。 学生必须翻动较大的页面,寻找所需日期的时间表。 此外,在脱机模式下,日程表将不可用。
我决定制作一个小型应用程序,可以根据我的学院的日程安排对该站点进行解析,并且具有以下优点:
- 显示:当前星期几,日期,星期几和该日的时间表
- 使用“后退”和“下一个”按钮滚动时间表的能力
- 如果没有Internet,请显示日程表的最新下载的脱机版本
继续执行
因此,卷起袖子,我开始工作。 您需要从小做起。 即从编辑清单文件开始。 值得记住的是,我们的应用程序可以与Internet一起使用,并且获得适当的许可对于我们非常重要:
清单文件转到清单-> AndroidManifest.xml。 添加权限。 结果是这样的:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
现在让我们进入界面。 现在,让我们专注于功能而不是滥用小部件。 因此,我只放置了四个小部件:标题,文本框和按钮:来回。
活动标记 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/WeekNumber" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=" " app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/timetable" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="100dp" android:ems="10" android:inputType="textMultiLine" android:text="" app:layout_constraintTop_toBottomOf="@+id/WeekNumber" tools:layout_editor_absoluteX="0dp" /> <Button android:id="@+id/next" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" app:layout_constraintBottom_toBottomOf="parent" tools:layout_editor_absoluteX="0dp"></Button> <Button android:id="@+id/down" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" app:layout_constraintBottom_toTopOf="@+id/next" tools:layout_editor_absoluteX="0dp"></Button> </androidx.constraintlayout.widget.ConstraintLayout>
现在让我们开始解析。 这就是出色的开源解析器Jsoup帮助我们的地方。 我立即使用WebView取消了该选项,因为我发现此方法极为不便。 另外,我真的不想使用额外的小部件,没有它,您可以轻松地做到。
Jsoup连接将依赖项添加到build.gradle中:
implementation 'org.jsoup:jsoup:1.11.1'
不要忘记,使用Android版Web是一项艰巨的任务。 为了防止应用程序挂起,您需要使用位于UI流外部的Web。 因此,我们将使用AsyncTask类。 我们将基本功能放入其中,然后将数据传输到UI流。
对于那些不熟悉AsyncTask的人,我想说的是,该类应该位于您的活动的类内。 该类本身如下所示。
具有AsyncTask类的活动代码 package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class MainActivity extends AppCompatActivity { public boolean offline; public String request; public String WeekNumber; public int count;
结果,我们以这种形式获得数据:
让我们分析一下我们使用的方法:
创建类型为Document的元素
Document document = null;
我们得到页面
document = Jsoup.connect(url).get();
现在我们得到了body标签的内容
answer = document.body().html();
Jsoup还可以检索其他核心标记的内容。 例如,您可以使用title()方法等获取页面标题。 HTML()方法返回html代码,而text()是不带html标签的纯文本。
收到html代码后,您可以将其转换为纯文本,并删除所有标签。 这可以使用parse(htmlcode).text()完成:
return Jsoup.parse(answer).text();
我想分享一些未使用的更有用的Jsoup方法:
Element link = document.select("tag");
上方扰流板中的图片是一个为期一周的时间表的示例。 实际上,将有20个这样的星期返回给我们。 现在,我们的任务是在该数据集中找到今天并显示它。
想到
那我们有什么呢? 我们学习了如何将页面的html代码转换为易于解析的字符串。 使用字符串方法.split()和.replace()可以轻松完成此操作。
通常,该算法将如下所示。
首先,我们从Android获得所需的日期。 然后我们执行两个循环,一个循环嵌套在另一个循环中。 第一个周期贯穿数周,第二个周期位于内部,贯穿一周中的几天。 如果当天的日期与从Android收到的日期一致,那么我们会在文本框中显示当天的时间表。 但是,每个人都可以用自己的方式编写此算法。 我附上了其实现的版本。
完整的活动代码 package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class MainActivity extends AppCompatActivity { public boolean offline; public String request; public String WeekNumber; public int count;
提取时间表是在formatting()方法中进行的。 通过向输入法提交日期,我们将获得当天的时间表。 因此,我们可以轻松实现按钮“后退”和“下一步”的代码
下一步按钮代码:
count++; Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR,count); Date dayformat = calendar.getTime(); SimpleDateFormat format = new SimpleDateFormat("dd MMMM"); formating(format.format(dayformat));
使用日历,我们可以获得今天的日期。 使用add方法,我们将计数的天数与今天的日期相加。 后退按钮的代码将相似,仅计数需要减小该值。
结论
当然,您可以进行设计,但这是另一个主题。 我只是想分享基本技术。 在下面的剧透中,我附上了经过改进的屏幕截图。 我还添加了一些功能,例如:设置,选择研究组的能力等。 我一想到它,便可以稍后查看该应用程序本身。