Android编写简单的网络爬虫

一、网络爬虫的基本知识

网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念。爬虫如何遍历网络呢,互联网可以看做是一张大图,每个页面看做其中的一个节点,页面的连接看做是有向边。图的遍历方式分为宽度遍历和深度遍历,但是深度遍历可能会在深度上过深的遍历或者陷入黑洞。所以,大多数爬虫不采用这种形式。另一方面,爬虫在按照宽度优先遍历的方式时候,会给待遍历的网页赋予一定优先级,这种叫做带偏好的遍历。

实际的爬虫是从一系列的种子链接开始。种子链接是起始节点,种子页面的超链接指向的页面是子节点(中间节点),对于非html文档,如excel等,不能从中提取超链接,看做图的终端节点。整个遍历过程中维护一张visited表,记录哪些节点(链接)已经处理过了,跳过不作处理。

二、Android网络爬虫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基于Jsoupcontent搞成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;
          }
        }
      }
    }
  }
}

以上就是基于Android编写简单的网络爬虫的全部内容,本文介绍的很详细,希望给大家在Android开发的过程中有所帮助。

(0)

相关推荐

  • Android利用爬虫实现模拟登录的实现实例

    Android利用爬虫实现模拟登录的实现实例 为了用手机登录校网时不用一遍一遍的输入账号密码,于是决定用爬虫抓取学校登录界面,然后模拟填写本次保存的账号.密码,模拟点击登录按钮.实现过程折腾好几个. 一开始选择的是htmlunit解析登录界面html,在pc上测的能实现,结果在android上运行不起来,因为htmlunit利用了javax中的类实现的解析,android不支持javax,所以就跑不起来. 不过pc还是ok的 实例代码: package com.yasin; import jav

  • Android编写简单的网络爬虫

    一.网络爬虫的基本知识 网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念.爬虫如何遍历网络呢,互联网可以看做是一张大图,每个页面看做其中的一个节点,页面的连接看做是有向边.图的遍历方式分为宽度遍历和深度遍历,但是深度遍历可能会在深度上过深的遍历或者陷入黑洞.所以,大多数爬虫不采用这种形式.另一方面,爬虫在按照宽度优先遍历的方式时候,会给待遍历的网页赋予一定优先级,这种叫做带偏好的遍历. 实际的爬虫是从一系列的种子链接开始.种子链接是起始节点,种子页面的超链接指向的页面是

  • 教你如何编写简单的网络爬虫

    一.网络爬虫的基本知识 网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念.爬虫如何遍历网络呢,互联网可以看做是一张大图,每个页面看做其中的一个节点,页面的连接看做是有向边.图的遍历方式分为宽度遍历和深度遍历,但是深度遍历可能会在深度上过深的遍历或者陷入黑洞.所以,大多数爬虫不采用这种形式.另一方面,爬虫在按照宽度优先遍历的方式时候,会给待遍历的网页赋予一定优先级,这种叫做带偏好的遍历. 实际的爬虫是从一系列的种子链接开始.种子链接是起始节点,种子页面的超链接指向的页面是

  • Android编程简单获取网络上的图片

    本文实例讲述了Android编程简单获取网络上的图片的方法.分享给大家供大家参考,具体如下: 要获取网络上的图片,首先得有网络的访问权限,这个不再写了,以前的文章中写过,还有布局方式不再写了,就是写也是一个简单的布局,没有多大意义,直接上核心代码: 这是本人使用的一个简单的类,来获取网上的图片. public static Bitmap getImage(String Url) throws Exception { try { URL url = new URL(Url); String res

  • java实现一个简单的网络爬虫代码示例

    目前市面上流行的爬虫以python居多,简单了解之后,觉得简单的一些页面的爬虫,主要就是去解析目标页面(html).那么就在想,java有没有用户方便解析html页面呢?找到了一个jsoup包,一个非常方便解析html的工具呢. 使用方式也非常简单,引入jar包: <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.8.

  • Selenium结合BeautifulSoup4编写简单的python爬虫

    在学会了抓包,接口请求(如requests库)和Selenium的一些操作方法后,基本上就可以编写爬虫,爬取绝大多数网站的内容. 在爬虫领域,Selenium永远是最后一道防线.从本质上来说,访问网页实际上就是一个接口请求.请求url后,返回的是网页的源代码. 我们只需要解析html或者通过正则匹配提取出我们需要的数据即可. 有些网站我们可以使用requests.get(url),得到的响应文本中获取到所有的数据.而有些网页数据是通过JS动态加载到页面中的.使用requests获取不到或者只能获

  • java编程实现简单的网络爬虫示例过程

    本项目中需要用到两个第三方jar包,分别为 jsoup 和 commons-io. jsoup的作用是为了解析网页, commons-io 是为了把数据保存到本地. 1.爬取贴吧 第一步,打开eclipse,新建一个java项目,名字就叫做 pachong: 然后,新建一个类,作为我们程序的入口. 这个作为入口类,里面就写一个main方法即可. public class StartUp { public static void main(String[] args) { } } 第二步,导入我们

  • 用Python编写简单的微博爬虫

    先说点题外话,我一开始想使用Sina Weibo API来获取微博内容,但后来发现新浪微博的API限制实在太多,大家感受一下: 只能获取当前授权的用户(就是自己),而且只能返回最新的5条,WTF! 所以果断放弃掉这条路,改为『生爬』,因为PC端的微博是Ajax的动态加载,爬取起来有些困难,我果断知难而退,改为对移动端的微博进行爬取,因为移动端的微博可以通过分页爬取的方式来一次性爬取所有微博内容,这样工作就简化了不少. 最后实现的功能: 1.输入要爬取的微博用户的user_id,获得该用户的所有微

  • 使用Python的Twisted框架编写简单的网络客户端

    Protocol   和服务器一样,也是通过该类来实现.先看一个简短的例程: from twisted.internet.protocol import Protocol from sys import stdout class Echo(Protocol): def dataReceived(self, data): stdout.write(data) 在本程序中,只是简单的将获得的数据输出到标准输出中来显示,还有很多其他的事件没有作出任何响应,下面 有一个回应其他事件的例子: from t

  • Android编写简单的聊天室应用

    最近写了一个简单的聊天室应用,可以发送表情,更改头像这些功能.主要技术点就是怎样把表情图片放到textview等Ui控件中展示.这里废话不多说,下面是效果图: 这里主要讲下怎样把文本替换到表情,先说下思路,首先我们的图片是保存在本地资源目录drawable中而所有的资源文件都是R这个类来管理,所以我们可以利用正则表达式找出图片id包装成ImageSpan然后把ImageSpan放到SpannableString中,最后把SpannableString放入edittext中,下面是源码: pack

  • 从零学习node.js之简易的网络爬虫(四)

    前言 之前已经介绍了node.js的一些基本知识,下面这篇文章我们的目标是学习完本节课程后,能进行网页简单的分析与抓取,对抓取到的信息进行输出和文本保存. 爬虫的思路很简单: 确定要抓取的URL: 对URL进行抓取,获取网页内容: 对内容进行分析并存储: 重复第1步 在这节里做爬虫,我们使用到了两个重要的模块: request : 对http进行封装,提供更多.更方便的接口供我们使用,request进行的是异步请求.更多信息可以去这篇文章上进行查看 cheerio : 类似于jQuery,可以使

随机推荐