最近在学习一些material design下的控件的使用以及MVP框架,就索性做了一个APP来练练手,APP主要的功能就是通过爬虫从学校的新闻网网页上抓取新闻,然后显示在APP上。下面是展示的效果。
这是主界面的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="256dp"
android:fitsSystemWindows="true"
app:contentScrim="@color/colorPrimaryDark"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/app_bar_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/bg"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
android:id="@+id/toolbar_tab"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:background="#ffffff"
android:fillViewport="false"
app:layout_scrollFlags="scroll"
app:tabIndicatorColor="#0835f8"
app:tabIndicatorHeight="2.0dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="#0835f8"
app:tabTextColor="#ced0d3">
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="头条新闻" />
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="校园新闻" />
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="学术新闻" />
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="民大人物" />
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="校园纵横" />
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="理论学习" />
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="媒体民大" />
</android.support.design.widget.TabLayout>
>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_news_home" />
</android.support.design.widget.CoordinatorLayout>
主要内容是include中的布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.v4.widget.NestedScrollView>
就是通过ViewPager+Fragment来显示新闻内容
从网页上抓取数据,用的是Jsoup,CrawlerUtils.java里面就是处理从网页上抓取数据的逻辑:
package cn.swun.sp.stu.news_swun.utils;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import cn.swun.sp.stu.news_swun.Bean.New;
/**
* Create time : 2016/6/4.
* Created by :saipeng
* Description:
*/
public class CrawlerUtils {
private static final String TAG = "CRAWLER";
private static String next_url;
public static String getNext_url() {
return next_url;
}
public static void setNext_url(String next_url) {
CrawlerUtils.next_url = next_url;
}
public static ArrayList<String> getDetailToNew(String url) {
Document doc = getDocument(url);
if (doc == null) return null;
return getDetailContent(doc);
}
@NonNull
private static ArrayList<String> getDetailContent(Document doc) {
ArrayList<String> infos = new ArrayList<>();
//先获取第一段内容
infos.add(doc.select("div.page_detail").first().getElementsByTag("p").first().text());
//再获取第一张图片的url
infos.add(doc.getElementsByTag("img").first().attr("abs:src"));
//解析详细的时间
infos.add(doc.select("div.newsTime").first().getElementsByTag("span").first().text());
//接着对详细内容进行解析
Elements elements = doc.select("div.page_detail").first().getElementsByTag("p");
Log.i(TAG, "elements:" + elements.size());
for (Element e : elements) {
Element img = e.getElementsByTag("img").first();
if (img != null) {
infos.add(img.attr("abs:src"));
} else {
infos.add(e.text());
}
}
for (String s : infos) {
Log.i(TAG, s);
}
return infos;
}
//得到新闻的第一张图片资源以及第一段文本
public static String[] getUrlByTitle(String url) {
Document doc = getDocument(url);
if (doc == null) return null;
String[] result = new String[2];
result[0] = doc.select("div.page_detail").first().getElementsByTag("p").first().text();
result[1] = doc.getElementsByTag("img").first().attr("abs:src");
return result;
}
public static List<New> getNewsByType(String url) {
Document doc = getDocument(url);
if (doc == null) return null;
Elements elements = doc.select("li[id]");
Log.i(TAG, "elements:" + elements.size());
//抓取下一页的url
Element e = doc.select("a.Next").first();
if (e != null) {
next_url = e.attr("abs:href");
Log.i(TAG, "next_url:" + next_url);
} else {
next_url = "";
}
if (elements.size() != 0 && elements != null) {
List<New> news = new ArrayList<>();
for (Element element : elements) {
String time = element.getElementsByTag("span").text();
String content = element.getElementsByTag("a").text();
String href = element.getElementsByTag("a").attr("abs:href");
ArrayList<String> infos = getDetailToNew(href);
news.add(new New(time, content, href, infos));
}
return news;
}
return null;
}
@Nullable
private static Document getDocument(String url) {
Connection conn = Jsoup.connect(url);
conn.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/ 20100101 Firefox/32.0");
Document doc = null;
try {
doc = conn.cookie("cookie", "sp").timeout(3000).get();
if (doc == null) {
Log.i(TAG, "document is null");
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
return doc;
}
}
源码请移步到:App源码