Android 网络爬虫demo

嗯………………………………………
我也不懂爬虫是什么意思 就是从网页上扒数据吧应该是这样
所以这个demo抓取的是我们学校新闻网页的东西
看一下效果
这里写图片描述

抓的是这个网页 然后写了一个APP
是这样的
这里写图片描述这里写图片描述

把listview做成卡片式的了 然后配色弄的也很有纸质感啊啊啊
反正自己还挺喜欢的
然后就看看是怎么弄的
这里写图片描述

看一下每个类都是干啥的 :
MainActivity:主界面的Activity
MainAdapter:listview的适配器
NetWorkClass:链接网络 使用HttpClient发送请求、接收响应得到content 大概就是拿到了这个网页的什么鬼东西
还有好多就是一个html的代码 要解析这个
News:这个类里有两个属性 一个标题 一个是这个标题新闻点进去那个url;
NewsActivity:详细新闻界面
PullListView:重写了listview 具有下拉刷新和上拉加载功能

然后从oncreat()开始看:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InitView();
        MainThread mt = new MainThread(newsUrl);
        final Thread t = new Thread(mt, "MainThread");
        t.start();

        pullListView.setOnRefreshListener(new PullListView.OnRefreshListener() {
            @Override
            public void onRefresh() {
                isGetMore = false;
                MainThread mt = new MainThread(newsUrl);
                Thread t = new Thread(mt, "MainThread");
                t.start();

            }
        });

        pullListView.setOnGetMoreListener(new PullListView.OnGetMoreListener() {
            @Override
            public void onGetMore() {
                isGetMore = true;
                if (num > 1) {
                    MainThread mt = new MainThread(nextPage);
                    Thread t = new Thread(mt, "MainThread");
                    t.start();
                }

            }
        });
        pullListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(MainActivity.this,NewsActivity.class);
                intent.putExtra("url",list.get(position-1).getUrl());
                startActivity(intent);

            }
        });

    }

这个里面主要就是先初始化了数据
然后new了一个线程 因为涉及到了网络请求 所以我们要开线程去执行 然后有一些listview的下拉上拉点击的绑定
所以主要内容是在线程里面
再看线程之前 先看一下networkClass

package com.example.katherine_qj.news;

import android.net.http.HttpResponseCache;
import android.util.Log;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * Created by Katherine-qj on 2016/7/24.
 */
public class NetWorkClass {
    public String getDataByGet(String url){
        Log.e("qwe","content");
        String content ="";
        HttpClient httpClient = new DefaultHttpClient();
        Log.e("qwe","content1");
        /*使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
        1. 创建HttpClient对象。
        2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
        3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
        4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
        5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
        6. 释放连接。无论执行方法是否成功,都必须释放连接*/
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse httpResponse = httpClient.execute(httpGet);
           // HttpReponse是服务器接收到浏览器的请求后,处理返回结果常用的一个类。
            if(httpResponse.getStatusLine().getStatusCode() == 200) {
                /*getStatusLine()
               获得此响应的状态行。状态栏可以设置使用setstatusline方法之一,也可以在构造函数初始化*/
                InputStream is = httpResponse.getEntity().getContent();
                /*getEntity()
                获取此响应的消息实体,如果有。实体是通过调用setentity提供。*/
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = reader.readLine()) != null){
                    content += line;
                }
            }
        }catch (IOException e)
        {
            Log.e("http",e.toString());
        }
        Log.e("sdf",content);
        return  content;
    }
}

注释的很详细了
大概就是 有一个getDataByGet方法 然后接受一个url参数 经过一系列请求得到网页内容 返回一个content
下来就是使用这个类的线程了

 public class MainThread implements  Runnable{
        private String url;
        public MainThread(String url){
            this.url = url;
        }
        @Override
        public void run() {
            NetWorkClass netWorkClass =new NetWorkClass();//new 了一个network类
            content = netWorkClass.getDataByGet(url);//接收这个类返回的那个字符串也就是需要解析的那一串
            Log.e("qwe",content);
            handler.sendEmptyMessage(111);
        }
    }

就是利用这个线程去得到content 然后通过handle传递到主线程去解析

     private final android.os.Handler handler = new android.os.Handler(){
       public  void  handleMessage(Message msg){
           switch (msg.what){
               case 111:
                   analyseHTML();
                   if(isGetMore){
                        mainAdapter.notifyDataSetChanged();
           /*每一次notifyDataSetChange()都会引起界面的重绘。当需要修改界面上View的相关属性的时候,
             最后先设置完成再调用notifyDataSetChange()来重绘界面。*/
                   }else {
                       mainAdapter = new MainAdapter(MainActivity.this, list);
                       pullListView.setAdapter(mainAdapter);
                   }
                   pullListView.refreshComplete();
                   pullListView.getMoreComplete();
                   break;
           }
       }
     };

analyseHTML();
发现其实解析的东西在这个方法里面 所以 这里才是解析网页的东西啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊:

 public void analyseHTML(){
         if(content!=null){
             int x= 0;
             Document  document = Jsoup.parse(content);
             //解析HTML字符串
             if (!isGetMore) {
                 list.clear();
                 Element element = document.getElementById("fanye3942");//拿到fanye3942这个节点
                 String text = element.text();//得到这个节点的文本部分
                 System.out.print(text);
                 num = Integer.parseInt(text.substring(text.lastIndexOf('/') + 1, text.length() - 1));
                 System.out.print(num);
             }
                 Elements elements = document.getElementsByClass("c3942");//得到c3942这个节点中的所有子节点
                 while(true){
                    if(x==elements.size()){
                        System.out.print(elements.size());
                        break;//遍历到最后就退出
                    }
                     News news = new News();
                     news.setTitle(elements.get(x).attr("title"));//分别得到每一个子节点的需要的文本部分
                     news.setUrl(elements.get(x).attr("href"));
                    // list.add(news);
                     if (!isGetMore||x>10){
                         list.add(news);
                         if(x>=25){
                             break;
                         }//这个是因为我们学校的网页有重复
                     }
                     x++;

                 }
                 if (num>1){
                     nextPage = url+"/"+ --num+".htm";//因为有翻页这里得到了下一页的url在上拉的时候会开启线程去请求数据
                     System.out.println("qqqqqqqqqqq"+nextPage);
                 }

             }
         }

Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。
所以android基于Jsoup 把content搞成Document 对象
然后就可以慢慢分解去拿了 然后拿哪里的数据就要看需要了
我开始一直不知道那些fanye3942 和c3942是啥 后来才知道是需要的数据的节点id或者class
这里写图片描述
就像这样
然后把每一次遍历的数据都加到集合里面 给listview绑定集合就好了

大概主页面就是这样 然后跳转页面 就是因为news里面还放入了每一个新闻点击之后的url所以传到NewsActivity中再利用相同的思路去解析显示就好了

package com.example.katherine_qj.news;

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;

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

/**
 * Created by Katherine-qj on 2016/7/25.
 */
public class NewsActivity extends Activity {
    private TextView textTitle;
    private TextView textEdit;
    private TextView textDetail;
    private String title;
    private String edit;
    private String  detail;
    private StringBuilder text;
    private String url;
    private Document document;
    private String  content;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news);
        InitView();
        url=getIntent().getStringExtra("url");
        Log.e("qqq",url);
        NewsThread newsThread = new NewsThread(url);

        final Thread t = new Thread(newsThread,"NewsActivity");
        t.start();

    }
    public void InitView(){
        textTitle =(TextView)findViewById(R.id.textTitle);
        textEdit =(TextView)findViewById(R.id.textEdit);
        textDetail = (TextView)findViewById(R.id.textDetail);
    }
    private final android.os.Handler handler = new android.os.Handler(){
      public  void handleMessage(Message msg){
          if(msg.what==1001){
              document = Jsoup.parse(content);
              analyseHTML(document);
              textTitle.setText(title);
              textEdit.setText(edit);
              textDetail.setText(text);
          }

      }
    };
    public class  NewsThread implements  Runnable{
        String url;
        public NewsThread(String url){
            this.url = url;
        }
        @Override
        public void run() {

            NetWorkClass netWorkClass = new NetWorkClass();
            content = netWorkClass.getDataByGet(url);
            System.out.print("qqq"+content);
            handler.sendEmptyMessage(1001);
        }


    }
    public void analyseHTML(Document document){
        if (document!=null){
            Element element = document.getElementById("nrys");
            Elements elements = element.getAllElements();
            title = elements.get(1).text();
            edit = elements.get(4).text();
            Element mElement = document.getElementById("vsb_content_1031");
            if(mElement != null) {
                Elements mElements = mElement.getAllElements();
                text = new StringBuilder();
                for (Element melement : mElements) {
                    if(melement.className().equals("nrzwys") || melement.tagName().equals("strong")){
                        continue;
                    }

                    if(!melement.text().equals(" ") && !melement.text().equals(""));{
                        text.append("  ").append(melement.text()).append("\n");
                    }
                    if (melement.className().equals("vsbcontent_end")) {
                        break;
                    }
                }
            }
        }
    }
}

然后这个demo就写好了 可以试着去再弄一些别的网页
有人吐槽我android代码写得好丑 和C语言一样
哈哈哈哈哈哈
现在想起来这个突然好好笑。

over!

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值