1.使用Andriod Studio的http解析器
Android Studio 在高版本后自带了Jsoup解析器,要使用Jsoup解析器,首先要在
scripts:build.gradle:dependencies```中加入```implementation 'org.jsoup:jsoup:1.9.2'``` ,其后,在class里可以使用```import org.jsoup.Jsoup;``` 导入。Android Studio 默认关闭了APP的网络访问,所以要在```manifests:AndroidManifest.xml```1 2 3 4
| 中加入两行代码
```<usespermissionandroid:name="android.permission.INTERNET" />
|
android:name1 2 3 4 5 6 7 8 9 10 11 12 13
| <!-- more --> #### 2.获取以及解析静态网页
##### (1)获取网页
首先创建一个```private Document getDocument(Stirng url)``` ,以Math1310的课程网页为例,令```String url = "http://math.yorku.ca/~lishu3/math1310.html" ``` 此时,构建一个简单的 try catch模块。
```java try{ return Jsoup.connect(url).timeout(5000).get(); }catch (IOException e){ e.printStackTrace(); }
|
需要注意的是,Jsoup.connect后需要加get()才能取得解析结果,而timeout则要加在两者之间。
这个function 返回的Document格式是Jsoup独有的格式。所以需要导入import org.jsoup.nodes.Document
才不会报错。
(2)解析网页
首先分析网页结构
需要抓取的结构通过分析我们可以看出位于<ul></ul>
内 , 此时令Document doc = getDocument(url)
添加Jsoup选择器Element ul = doc.select("ul").first()
这段代码的意思是从整个被解析出的html文件中选取第一个ul作为Element。需要注意的是,这个网页中含有两个<ul>
element 而如果不使用.first()
去选择第一个ul作为element则必须使用Elements
作为数据容器。
此时我们已经选择第一个<ul>
作为目标,使用 Elements elements= ul.select("li");
选取ul内所有的li作为目标。 迭代循环并输出每一个element的内容。
3.多线程更新View
在Android中,原始的主线程不允许参与与网络有关的模块运行,因为非常容易造成卡顿,那么要运行刚刚的程序,必须开启一个新的线程。
1 2 3 4 5
| new Thread(){ @Override public void run(){ } }.start();
|
而如果要更新View,则必须使用Handler才能进行
1 2 3
| Handler handler=new Handler(); 以及 handler.post();
|
但是如果直接使用两者来setContentoftextView就会遇到一个问题:报错
1
| android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
|
翻译过来就是,只有创建view的那个线程(这里是主线程)才能跟新view,而我们创建的子线程new thread如果直接运行setContentOfTextView则会报错。
这里就要使用这种方法才能避开这个问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| new Thread(){ @Override public void run(){ GetInfo info=new GetInfo(); final String output=info.getInfo("http://math.yorku.ca/~lishu3/math1310.html"); handler.post(new Runnable() { @Override public void run() { setContentOftextView(R.id.outputInfo,output); } }); }
}.start();
|
通过在handler.post里再创建一个新的Runnable event在里面跑setContentofTextView就可以成功的避开这个问题了。
4.GGWP其他一些小的经验
(1)在设置textView的时候,如果加一行textView.setMovementMethod(ScrollingMovementMethod.getInstance());
则textview可以触屏滚动
(2)在制作这个简单的爬虫APP的时候,我并没有考虑脱离网络的情况,实际上,如果不加入判断手机是否有网络的代码,则这个APP会直接崩溃,推荐在之后的APP里加入判断手机是否有Wifi或者是数据的功能。