动态网络爬虫android_android网络爬虫 - CSDN
  • 希望了解如何用java语言爬虫网页的可以看下。 杂家前文就又介绍用HTTP访问百度主页得到html的string字符串,但html的文本数据如果不经过处理就是个文本字符串没有任何效果的。所谓的浏览器就是负责将文本的html...

    本文参考鸿洋大大链接详细介绍如何使用Jsoup包抓取HTML数据,是一个纯java工程,并将其打包成jar包。希望了解如何用java语言爬虫网页的可以看下。

    杂家前文就又介绍用HTTP访问百度主页得到html的string字符串,但html的文本数据如果不经过处理就是个文本字符串没有任何效果的。所谓的浏览器就是负责将文本的html“翻译”成看到的界面。在前文有介绍,这个csdn的客户端app分首页、业界、移动、研发、程序员、云计算五大类。以业界为例,http://news.csdn.net/ 实际加上page1的http地址是:http://news.csdn.net/news/1

    从上图可知,一个完整的新闻包含东西还是比较多的,将其抽象出来ID号、标题、链接、日期、图片链接、内容、类型,这7个属性。

    一、新建org.yanzi.bean包,里面有两个java文件

    NewsItem.java是上面具有7个属性的新闻bean

    package org.yanzi.bean;
    
    public class NewsItem
    {
    	private int id;
    
    	/**
    	 * 标题
    	 */
    	private String title;
    	/**
    	 * 链接
    	 */
    	private String link;
    	/**
    	 * 发布日期
    	 */
    	private String date;
    	/**
    	 * 图片的链接
    	 */
    	private String imgLink;
    	/**
    	 * 内容
    	 */
    	private String content;
    
    	/**
    	 * 类型  
    	 * 
    	 */
    	private int newsType;
    
    	public int getNewsType()
    	{
    		return newsType;
    	}
    
    	public void setNewsType(int newsType)
    	{
    		this.newsType = newsType;
    	}
    
    	public String getTitle()
    	{
    		return title;
    	}
    
    	public void setTitle(String title)
    	{
    		this.title = title;
    	}
    
    	public String getLink()
    	{
    		return link;
    	}
    
    	public void setLink(String link)
    	{
    		this.link = link;
    	}
    
    	public int getId()
    	{
    		return id;
    	}
    
    	public void setId(int id)
    	{
    		this.id = id;
    	}
    
    	public String getDate()
    	{
    		return date;
    	}
    
    	public void setDate(String date)
    	{
    		this.date = date;
    	}
    
    	public String getImgLink()
    	{
    		return imgLink;
    	}
    
    	public void setImgLink(String imgLink)
    	{
    		this.imgLink = imgLink;
    	}
    
    	public String getContent()
    	{
    		return content;
    	}
    
    	public void setContent(String content)
    	{
    		this.content = content;
    	}
    
    	@Override
    	public String toString()
    	{
    		return "NewsItem [id=" + id + ", title=" + title + ", link=" + link + ", date=" + date + ", imgLink=" + imgLink
    				+ ", content=" + content + ", newsType=" + newsType + "]";
    	}
    
    }
    

    CommonException.java 这个主要是抛出异常,方便构造

    package org.yanzi.bean;
    
    public class CommonException extends Exception
    {
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    
    	public CommonException()
    	{
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    	public CommonException(String message, Throwable cause)
    	{
    		super(message, cause);
    		// TODO Auto-generated constructor stub
    	}
    
    	public CommonException(String message)
    	{
    		super(message);
    		// TODO Auto-generated constructor stub
    	}
    
    	public CommonException(Throwable cause)
    	{
    		super(cause);
    		// TODO Auto-generated constructor stub
    	}
    	
    }
    

    二、新建org.yanzi.csdn包,这里放三个java文件

    Constant.java 这块将其弄成interface比较奇怪哈,写成class也ok

    package org.yanzi.csdn;
    
    public interface Constant
    {
    	public static final int NEWS_TYPE_YEJIE = 1; //业界
    	public static final int NEWS_TYPE_YIDONG = 2; //移动
    	public static final int NEWS_TYPE_YANFA = 3; //研发
    	public static final int NEWS_TYPE_CHENGXUYUAN = 4;//程序员
    	public static final int NEWS_TYPE_YUNJISUAN = 5; //云计算
    	
    
    }
    

    URLUtil.java 这个负责获取到每个大类新闻的精确的url地址

    package org.yanzi.csdn;
    
    
    public class URLUtil
    {
    
    
    	public static final String NEWS_LIST_URL = "http://www.csdn.net/headlines.html";
    	public static final String NEWS_LIST_URL_YIDONG = "http://mobile.csdn.net/mobile";
    	public static final String NEWS_LIST_URL_YANFA = "http://sd.csdn.net/sd";
    	public static final String NEWS_LIST_URL_YUNJISUAN = "http://cloud.csdn.net/cloud";
    	public static final String NEWS_LIST_URL_ZAZHI = "http://programmer.csdn.net/programmer";
    	public static final String NEWS_LIST_URL_YEJIE = "http://news.csdn.net/news";
    
    
    	/**
    	 * 根据文章类型,和当前页码生成url
    	 * @param newsType
    	 * @param currentPage
    	 * @return
    	 */
    	public static String generateUrl(int newsType, int currentPage)
    	{
    		currentPage = currentPage > 0 ? currentPage : 1;
    		String urlStr = "";
    		switch (newsType)
    		{
    		case Constant.NEWS_TYPE_YEJIE:
    			urlStr = NEWS_LIST_URL_YEJIE;
    			break;
    		case Constant.NEWS_TYPE_YANFA:
    			urlStr = NEWS_LIST_URL_YANFA;
    			break;
    		case Constant.NEWS_TYPE_CHENGXUYUAN:
    			urlStr = NEWS_LIST_URL_ZAZHI;
    			break;
    		case Constant.NEWS_TYPE_YUNJISUAN:
    			urlStr = NEWS_LIST_URL_YUNJISUAN;
    			break;
    		default:
    			urlStr = NEWS_LIST_URL_YIDONG;
    			break;
    		}
    
    
    		urlStr += "/" + currentPage;
    		
    		return urlStr;
    
    
    	}
    
    
    }

    DataUtil.java 利用HttpURLConnection 利用get方式获取html的文本,也就是string类型的数据. 注意这个文件跟上个文件封装上的松耦合性。

    package org.yanzi.csdn;
    
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    import org.yanzi.bean.CommonException;
    
    public class DataUtil {
    	/**
    	 * 获取HTML数据
    	 * @param urlStr url地址
    	 * @return
    	 * @throws CommonException
    	 */
    	public static String doGet(String urlStr) throws CommonException{
    		StringBuffer sb = new StringBuffer();
    		try {
    			URL url = new URL(urlStr);
    			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    			conn.setRequestMethod("GET");
    			conn.setConnectTimeout(5000);
    			conn.setDoInput(true);
    			conn.setDoOutput(true);
    			if(conn.getResponseCode() == 200){
    				InputStream is = conn.getInputStream();
    				int len = 0;
    				byte[] buf = new byte[1024];
    				while((len = is.read(buf)) != -1){
    					sb.append(new String(buf, 0, len, "UTF-8"));
    				}
    				is.close();
    			}else{
    				throw new CommonException("访问网络失败00");
    			}
    			
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    			throw new CommonException("访问网络失败11");
    		}
    		return sb.toString();
    	}
    }
    

    三、包名org.yanzi.biz,其下只有这个类,复杂完成真正的爬虫工作,即从html string字符串里提取出对应的新闻属性,存到新闻bean里

    package org.yanzi.biz;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    import org.yanzi.bean.CommonException;
    import org.yanzi.bean.NewsItem;
    import org.yanzi.csdn.DataUtil;
    import org.yanzi.csdn.URLUtil;
    
    /**
     * 处理NewItem的业务类
     * @author zhy
     * 
     */
    public class NewsItemBiz
    {
    	/**
    	 * 业界、移动、云计算
    	 * 
    	 * @param htmlStr
    	 * @return
    	 * @throws CommonException 
    	 */
    	public List<NewsItem> getNewsItems( int newsType , int currentPage) throws CommonException
    	{
    		String urlStr = URLUtil.generateUrl(newsType, currentPage);
    		
    		String htmlStr = DataUtil.doGet(urlStr);
    		
    		List<NewsItem> newsItems = new ArrayList<NewsItem>();
    		NewsItem newsItem = null;
    
    		Document doc = Jsoup.parse(htmlStr);
    		Elements units = doc.getElementsByClass("unit");
    		for (int i = 0; i < units.size(); i++)
    		{
    			newsItem = new NewsItem();
    			newsItem.setNewsType(newsType);
    
    			Element unit_ele = units.get(i);
    
    			Element h1_ele = unit_ele.getElementsByTag("h1").get(0);
    			Element h1_a_ele = h1_ele.child(0);
    			String title = h1_a_ele.text();
    			String href = h1_a_ele.attr("href");
    
    			newsItem.setLink(href);
    			newsItem.setTitle(title);
    
    			Element h4_ele = unit_ele.getElementsByTag("h4").get(0);
    			Element ago_ele = h4_ele.getElementsByClass("ago").get(0);
    			String date = ago_ele.text();
    
    			newsItem.setDate(date);
    
    			Element dl_ele = unit_ele.getElementsByTag("dl").get(0);// dl
    			Element dt_ele = dl_ele.child(0);// dt
    			try
    			{// 可能没有图片
    				Element img_ele = dt_ele.child(0);
    				String imgLink = img_ele.child(0).attr("src");
    				newsItem.setImgLink(imgLink);
    			} catch (IndexOutOfBoundsException e)
    			{
    
    			}
    			Element content_ele = dl_ele.child(1);// dd
    			String content = content_ele.text();
    			newsItem.setContent(content);
    			newsItems.add(newsItem);
    		}
    
    		return newsItems;
    
    	}
    
    }
    

    注意这个文件是真正的爬虫的核心,说明如下

    1、要爬虫一个html数据在之前可以使用HtmlParser,见链接http://www.cnblogs.com/loveyakamoz/archive/2011/07/27/2118937.html 但自从jsoup诞生后,使用比HtmlParser更方面。此处就是利用jsoup解析html的,需要加载lib文件夹下的jsoup-1.7.2.jar、jsoup-1.7.2-sources.jar,自己add to build path即可。后者是源码,可以查看,真正的包就第一个。

    2、jsoup可以直接打开一个网页url,此处为了方便已经写了从url获取string类型的html代码了。所以可以直接利用Document doc = Jsoup.parse(htmlStr); 得到Document类。

    以业界新闻为例,http://news.csdn.net/news/1,按快捷键ctrl+u查看其源码,搜索关键字unit可以看到:


    每一个新闻就是以关键字“unit”来标识的,第一页一共有10条新闻所以有10个unit。Elements units = doc.getElementsByClass("unit"); 得到这10个新闻item的集合。

    3、接下来就是对一个新闻提取具体信息了

    先来看其中一个完整的新闻html代码:

    <div class="unit">
    <h1><a href="http:www.csdn.net/article/2014-07-25/2820877" target="_blank" >微视、美拍等的春天,不是短视频应用的春天</a></h1>
    <h4>发表于<span class="ago">2014-07-25 16:52</span>|<span class="view_time">690次阅读</span>|<span class="num_recom">6条评论</span></h4>
    <dl>
    <dt>
    <a href="http:www.csdn.net/article/2014-07-25/2820877" target="_blank"><img src="http:cms.csdnimg.cn/article/201407/25/53d21abd54a77.jpg" alt="" /></a>
    </dt>
    <dd>微视、美拍等短视频应用最近很火,它们都已经在App Store社交免费榜靠前。它们的流行,能证明短视频应用的春天到了吗?小谦认为,非也。只有解决4G网络问题、分享问题以及拍摄优化问题后,它的春天才会真正到来。</dd>
    </dl>
    <div class="tag"><a href="http:www.csdn.net/tag/%E5%B0%8F%E8%B0%A6/news" target="_blank">小谦</a><a href="http:www.csdn.net/tag/%E5%BE%AE%E8%A7%86/news" target="_blank">微视</a><a href="http:www.csdn.net/tag/%E7%A7%92%E6%8B%8D/news" target="_blank">秒拍</a><a href="http:www.csdn.net/tag/%E7%BE%8E%E5%9B%BE%E7%A7%80%E7%A7%80/news" target="_blank">美图秀秀</a><a href="http:www.csdn.net/tag/%E7%BE%8E%E6%8B%8D/news" target="_blank">美拍</a><a href="http:www.csdn.net/tag/%E5%BE%AE%E4%BF%A1/news" target="_blank">微信</a><a href="http:www.csdn.net/tag/%E5%BA%94%E7%94%A8/news" target="_blank">应用</a><a href="http:www.csdn.net/tag/%E7%9F%AD%E8%A7%86%E9%A2%91/news" target="_blank">短视频</a></div>
    </div>

    从html代码上可以看到,新闻的标题是以<h1>标识的,所以用Element h1_ele = unit_ele.getElementsByTag("h1").get(0);得到一个Element。此处get(0),是因为h1标签的就有1个。

    h1标识里的代码是:

    <a href="http://www.csdn.net/article/2014-07-30/2820930" target="_blank" >IDC:全球智能机出货量涨23% 华为进前5且翻番</a>

    所以通过 Element h1_a_ele = h1_ele.child(0);
    String title = h1_a_ele.text();
    String href = h1_a_ele.attr("href");

    得到<a>标签里标识的东西。通过:

    String title = h1_a_ele.text();
    String href = h1_a_ele.attr("href");

    得到标题和链接。

    接下来通过h4的tag找日期:

    <h4>发表于<span class="ago">14小时前</span>|<span class="view_time">2944次阅读</span>|<span class="num_recom">17条评论</span></h4>

    通过class找到ago孩子,最终得到时间。

    其他的都类似了,从中可以看出如果是根据html外围的标签,用getElementsByTag("h1").get(0),如果里面包含的有class则要用getElementsByClass("ago").get(0)来进一步定位。如果没有class,只是普通的孩子,利用child(0)定位得到Element。


    最后是测试代码:

    Test.java

    package org.yanzi.test;
    
    import java.util.List;
    
    import org.yanzi.bean.CommonException;
    import org.yanzi.bean.NewsItem;
    import org.yanzi.biz.NewsItemBiz;
    import org.yanzi.csdn.Constant;
    
    
    
    public class Test
    {
    
    	public static void main(String[] args){
    		Test test = new Test();
    		test.test01();
    	}
    	
    	@org.junit.Test
    	public  void test01()
    	{
    		NewsItemBiz biz = new NewsItemBiz();
    		int currentPage = 1;
    		try
    		{
    			/**
    			 * 业界
    			 */
    			System.out.println("-----------业界-----------");
    			List<NewsItem> newsItems = biz.getNewsItems(Constant.NEWS_TYPE_YEJIE, currentPage);
    			for (NewsItem item : newsItems)
    			{
    				System.out.println(item);
    			}
    
    			/**
    			 * 程序员杂志
    			 */
    			System.out.println("-----------程序员-----------");
    			newsItems = biz.getNewsItems(Constant.NEWS_TYPE_CHENGXUYUAN, currentPage);
    			for (NewsItem item : newsItems)
    			{
    				System.out.println(item);
    			}
    			
    			/**
    			 * 研发
    			 */
    			System.out.println("-----------研发-----------");
    			newsItems = biz.getNewsItems(Constant.NEWS_TYPE_YANFA, currentPage);
    			for (NewsItem item : newsItems)
    			{
    				System.out.println(item);
    			}
    			
    			
    			/**
    			 * 移动
    			 */
    			System.out.println("-------------移动---------");
    			newsItems = biz.getNewsItems(Constant.NEWS_TYPE_YIDONG, currentPage);
    			for (NewsItem item : newsItems)
    			{
    				System.out.println(item);
    			}
    			System.out.println("-------------结束---------");
    
    		} catch (CommonException e)
    		{
    			e.printStackTrace();
    		}
    	}
    
    }
    运行结果:

    -----------业界-----------
    NewsItem [id=0, title=IDC:全球智能机出货量涨23% 华为进前5且翻番, link=http://www.csdn.net/article/2014-07-30/2820930, date=15小时前, imgLink=http://cms.csdnimg.cn/article/201407/30/53d844474e279.jpg, content=IDC日前发布了2014年第二季度全球智能手机市场相关的研究数据。数据显示,位居全球智???手机出货量前五的厂商分别是三星、苹果、华为、联想和LG。华为智能手机出货量更是同比大涨了近一倍,而三星却同比下降。, newsType=1]
    NewsItem [id=0, title=专访叶劲峰:漫谈游戏开发和游戏优化, link=http://www.csdn.net/article/2014-07-30/2820931, date=15小时前, imgLink=http://cms.csdnimg.cn/article/201407/30/53d85983915fe.jpg, content=社区之星第50期采访了腾讯互动娱乐研发部引擎技术中心专家工程师叶劲峰,他讲述了译著《游戏引擎架构》经历,并就游戏引擎、优化、游戏开发学习等进行了分享。与此同时,叶劲峰也将坐镇社区问答第8期回答大家问题。, newsType=1]
    NewsItem [id=0, title=修成正果:Mozilla正式任命Chris Beard为CEO, link=http://www.csdn.net/article/2014-07-29/2820918, date=2014-07-29 14:40, imgLink=http://cms.csdnimg.cn/article/201407/29/53d712420edcd.jpg, content=Mozilla正式任命临时CEO Chris Beard为正式CEO,其于2004年加入Mozilla,随后一直负责产品、营销、创新等方面的工作。后在风投公司担任高管,在创新和企业管理方面积累了很多经验。Beard被公认为最适合的CEO人选。, newsType=1]
    NewsItem [id=0, title=苹果和IBM成最佳搭档 微软谷歌或受威胁, link=http://www.csdn.net/article/2014-07-28/2820905-apple-ibm, date=2014-07-29 14:51, imgLink=http://cms.csdnimg.cn/article/201407/28/53d61d099020f.jpg, content=月中,苹果宣布与IBM达成独家合作协议,两家合作在很大程度上是互补的,因为他们分别专注于消费者和企业市场,合作后必在企业级市场推出更强大的产品。同时,他们的发展也会对微软、谷歌和黑莓等公司带来不利影响。, newsType=1]
    NewsItem [id=0, title=敢为人先:亚马逊推出3D定制和销售门户网站, link=http://www.csdn.net/article/2014-07-29/2820911, date=2014-07-29 08:21, imgLink=http://cms.csdnimg.cn/article/201407/29/53d6e919d6e7e.jpg, content=在线零售商亚马逊近日推出了一门户网站,该网站是一个3D打印产品的销售平台。用户可以根据自己的喜好,比如材料、大小、样式和颜色的个性化,来定制和购买3D产品。甚至只要喜欢,还可以将照片或喜好的话定制上去。, newsType=1]
    NewsItem [id=0, title=微软中国遭工商总局调查 或因涉及“不公平交易”, link=http://www.csdn.net/article/2014-07-29/2820910, date=2014-07-29 07:47, imgLink=http://cms.csdnimg.cn/article/201407/29/53d6dcefe99e0.jpg, content=日前,国家工商总局相关人员突访了微软位??我国北京、上海、广州和成都四地的办公室,正就一些事情展开问询,或因该公司涉及操作系统垄断问题和贿赂官员以换取软件合同等。, newsType=1]
    NewsItem [id=0, title=传智播客“2014年全国高校IT骨干教师研修班”火热开班, link=http://www.csdn.net/article/2014-07-28/2820886, date=2014-07-28 10:11, imgLink=http://cms.csdnimg.cn/article/201407/28/53d5b05190e1a_thumb.jpg, content=日前,由传智播客主办的“2014年全国高校IT骨干教师研修班”火热开班。本届研修班吸引了来自全国30多所院校,近60名IT类专业教师参加。接下来将分Android、Java、PHP、网页平面UI、.Net共5个班开展课程学习交流。, newsType=1]
    NewsItem [id=0, title=【畅言】从程序员到架构师的方法与逻辑, link=http://www.csdn.net/article/2014-07-28/2820883, date=2014-07-28 08:51, imgLink=http://cms.csdnimg.cn/article/201407/28/53d59d5f7d4ca.jpg, content=架构师这个词经常见到,很多人都冠着这个头衔,实际上很多人对架构师究竟是干什么的都没有统一的认识。V众投发起人李智勇则利用特定场景进行分析,诠释了架构师这个概念,并给出如何成为架构师方法。, newsType=1]
    NewsItem [id=0, title=Windows Phone 8.1 Update 1:图标可合并成文件夹、4G语音通话, link=http://www.csdn.net/article/2014-07-28/2820882, date=2014-07-28 07:52, imgLink=http://cms.csdnimg.cn/article/201407/28/53d58fc0ef514.jpg, content=微软终于计划发布已经进入RTM阶段的Windows Phone 8.1Update 1(或GDR1),可能包括:对图标进行拖拽以及合并成文件夹、支持1280 x 800屏幕分辨率和7英寸的设备、支持交互式的手机外壳(见上图),以及4G语音通话。, newsType=1]
    NewsItem [id=0, title=智能硬件生态未成,打造平台为时尚早, link=http://www.csdn.net/article/2014-07-28/2820881, date=2014-07-28 00:37, imgLink=null, content=当前的智能硬件产业发展是由创业公司探路,巨头纷纷跟进打造开放平台。但智能硬件市场至今无标杆性产品、开发者及应用前景不明、尚未找到用户“痛点”等特征表明市场仍处于萌芽阶段,打造平台为时尚早。, newsType=1]
    -----------程序员-----------
    NewsItem [id=0, title=Server SAN:云计算时代的弄潮儿, link=http://www.csdn.net/article/2014-07-28/2820902, date=2014-07-28 15:17, imgLink=http://cms.csdnimg.cn/article/201407/28/53d6087c3920e.jpg, content=Server SAN为何一时间能成为了高大上的东西?分布式存储说来并不新奇,2000年诸如GPFS、Lustre、Panasas及PVFS就出现了,但之后发展不温不火。说到底还是实际应用需求的推动,当前的繁荣源于数据在爆炸式增长。, newsType=4]
    NewsItem [id=0, title=大数据 “在路上”, link=http://www.csdn.net/article/2014-07-25/2820859, date=2014-07-25 11:03, imgLink=http://cms.csdnimg.cn/article/201407/25/53d1cfb8a3844.jpg, content=未来的Google无人驾驶汽车,一定像是一个移动的数据中心,需要同时处理着结构化、非结构化的大量数据,彼时的Big Data才算是真正用于汽车。, newsType=4]
    NewsItem [id=0, title=融合与统一:简评OS X10.10 Yosemite, link=http://www.csdn.net/article/2014-07-21/2820768, date=2014-07-21 17:09, imgLink=http://cms.csdnimg.cn/article/201407/23/53cf2e9689263.jpg, content=苹果旗下两大系列操作系统OS X和iOS发展步调并不一致。相对于iOS的迅猛发展,OS X显得不温不火。Yosemite的发布,应该说是个里程碑。本文基于Yosemite-Developer Preview 1.0版本简单介???这个OS X家族的新成员。, newsType=4]
    NewsItem [id=0, title=智能家居产品安全漫谈, link=http://www.csdn.net/article/2014-07-21/2820748, date=2014-07-21 11:06, imgLink=http://cms.csdnimg.cn/article/201407/21/53cc8931b917b.jpg, content=移动互联网技术的广泛应用为智能家居产业的发展提供了必要条件,无论传统巨头还是新兴创业公司都在投入这一领域,但随之而来的安全问题却未引起足够重视。, newsType=4]
    NewsItem [id=0, title=可穿戴计算机改变信息交互方式, link=http://www.csdn.net/article/2014-07-18/2820718, date=2014-07-18 09:51, imgLink=http://cms.csdnimg.cn/article/201407/18/53c8bf81c4723.jpg, content=可穿戴设备帮助我们更方便地感觉和捕捉世界,并且,我们也在以新的方式进行感官交流。未来几十年,可穿戴计算机将嵌入我们的衣服、珠宝甚至皮肤,而这将对人类信息交互方式产生很大影响。, newsType=4]
    NewsItem [id=0, title=高效能技术团队的协同工具箱, link=http://www.csdn.net/article/2014-07-16/2820681, date=2014-07-16 13:30, imgLink=http://cms.csdnimg.cn/article/201407/16/53c6483a059be.jpg, content=使用适合团队的协同工具,不但能使工作按预定成本如期顺利推进,而且能实现对团队成员、项目过程以及产品等的分析管理。未经调研就选择别人认为好的工具,很可能遭遇“水土不服”。, newsType=4]
    NewsItem [id=0, title=当虚拟照进现实——Oculus的世界梦, link=http://www.csdn.net/article/2014-07-14/2820639, date=2014-07-14 13:19, imgLink=http://cms.csdnimg.cn/article/201407/14/53c36d0be8cd1.jpg, content=专注虚拟现实设备研发的Oculus被Facebook以20亿美元收于麾下,Oculus公司创始人Palmer Luckey希望建立自己的虚拟现实硬件生产线,他还表示要从用户的角度来不断完善Rift,未来是属于用户的,而不仅仅是Oculus。, newsType=4]
    NewsItem [id=0, title=在动态网络下实现分布式共享存储, link=http://www.csdn.net/article/2014-07-09/2820585-implementing-distributed-shared-memory-for-dynamic-networks, date=2014-07-09 10:59, imgLink=http://cms.csdnimg.cn/article/201407/09/53bcddd2580b0.jpg, content=本文介绍了分布式环境下实现共享内存模型会遇到的各种问题和挑战,并针对不同问题介绍多种算法的优劣性。本文是对现阶段该领域研究现状的总体介绍,通过本文能了解动态分布式共享内存研究的前沿状况、挑战与机遇。, newsType=4]
    NewsItem [id=0, title=从Objective-C到Swift, link=http://www.csdn.net/article/2014-07-08/2820568, date=2014-07-08 11:22, imgLink=http://cms.csdnimg.cn/article/201407/09/53bcabb118d79.jpg, content=2014年WWDC大会,苹果在毫无预兆的情况下发布了Swift语言。Swift背后的概念大多与Objective-C类似,但更为简洁、自然,也吸收了很多其他语言的语法。本文将对Swift的语法、特点及改进进行全面介绍。, newsType=4]
    NewsItem [id=0, title=50年内有望实现的7大技术, link=http://www.csdn.net/article/2014-07-07/2820549, date=2014-07-07 10:43, imgLink=http://cms.csdnimg.cn/article/201407/07/53ba0dedb7494.jpg, content=1964年,美国电气与电子工程学会IEEE杂志《IEEE Spectrum》刚成立时,一些预想家就曾预测过50年后的科技走势,如今,这一切都发生了。现在又有一批预想家预测了未来50年的科技发展趋势。, newsType=4]
    -----------研发-----------

    最后通过Export---Java---JAR file将其打包。

    附个jsoup的相关链接:http://blog.csdn.net/yjflinchong/article/details/7743995


    源码下载链接:http://download.csdn.net/detail/yanzi1225627/7697313







    展开全文
  • Android网络爬虫程序(基于Jsoup) 摘要:基于 Jsoup 实现一个 Android 的网页抓取程序,抓取页面的内容并显示出来。写这个程序的主要目的是抓取海投网的宣讲会信息(公司、时间、地点)并在移动端显示,这样就...

    摘要:基于 Jsoup 实现一个 Android 的网络爬虫程序,抓取网页的内容并显示出来。写这个程序的主要目的是抓取海投网的宣讲会信息(公司、时间、地点)并在移动端显示,这样就可以随时随地的浏览在学校举办的宣讲会信息了。


    一、Jsoup简介

    Jsoup 是一个 Java 的开源HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常方便的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

    Jsoup主要有以下功能:

    • 从一个URL,文件或字符串中解析HTML;

    • 使用DOM或CSS选择器来查找、取出数据;

    • 对HTML元素、属性、文本进行操作;

    • 清除不受信任的HTML (来防止XSS攻击)

    好了,下面写几段代码来说明 Jsoup 是如何优雅的进行 HTML 文档处理的。首先,我们需要去Jsoup官网 下载Jsoup的jar包,然后加入项目的依赖库中。

    1) HTML解析

    Jsoup 可以从一个字符串、文件或者一个 URL 中解析HTML,解析的目的主要是为了得到一个干净完整的解析结果,并生成 Document 对象实例。

    // Parse a document from a String
    String html = "<html><head><title>神奕的博客</title></head>"
            +"<body><p>搭个博客写学习笔记!!</p></body></html>";
    Document doc = Jsoup.parse(html);
    
    // Load a Document from a File
    File input = new File("D://a.html");
    Document doc = Jsoup.parse(input, "UTF-8");
    
    // Load a Document from a URL
    Document doc = Jsoup.connect("http://example.com/").get();

    当加载和解析一个本地的HTML文件时,如果在加载文件的时候发生错误,将抛出 IOException,应作适当处理。

    2) 数据提取

    将HTML解析成一个Document之后,就可以使用传统的 DOM 方法进行数据抽取。例如:

    // 海投网
    String url = "http://xjh.haitou.cc/wh/uni-1/after/hold/page-1/";
    Document doc = Jsoup.connect(url).get();
    
    Elements elements = doc.getElementsByTag("company");
    for(Element e : elements) {
        System.out.println(e.text());
    }

    Document 对象和 Elements 对象提供了一系列类似于DOM的方法来查找元素,比如 getElementById(String id)、getElementsByTag(String tag) 等等。更多方法请看《Jsoup Cookbook》。

    另外,还可以使用 Selector 选择器(类似于CSS或jQuery语法)来查找元素。如下:

    // 海投网
    String url = "http://xjh.haitou.cc/wh/uni-1/after/hold/page-1/";
    Document doc = Jsoup.connect(url).get();
    
    // 通过标签company查找元素
    Elements company = doc.select("company");
    // 带有href属性的a元素
    Elements links = doc.select("a[href]");
    // 扩展名为.png的图片
    Elements pngs = doc.select("img[src$=.png]");
    // class等于content的div标签
    Element content = doc.select("div.content").first();

    选择器实现了非常强大和灵活的查找功能。select方法在Document、Element 或 Elements 对象中都可以使用,且是上下文相关的,因此可实现指定元素的过滤或者链式选择访问。select方法将返回一个Elements集合,并提供一组方法来抽取和处理结果。

    通过 DOM 方法或者 Selector 方法查找到一些 Elements 元素之后,我们需要从这些元素中取得数据,下面是几个常用的方法:

    • 取得一个属性的值,可以使用Node.attr(String key)方法;

    • 取得一个元素中的文本,可以使用Element.text()方法;

    • 取得元素或属性中的HTML内容,可用Element.html()Node.outerHtml()方法

    • 取得一个元素的 id :Element.id()

    • 取得一个元素的标签名:Element.tagName()

    • 取得一个元素的类名:Element.className()

    3) 数据修改

    在解析一个 Document 之后可能想修改其中的某些属性值、HTML或文本内容,然后再保存到磁盘或都输出到前台页面。例如:我们可以为文档中的所有图片增加可点击链接、修改链接地址或者是修改文本等。Jsoup 提供了很多方法用来进行修改,这里就不列举了,请移步 Jsoup Cookbook


    二、海投网的页面抓取

    海投网是一个为高校毕业生服务的招聘信息网,创始人是华中科技大学的毕业生。现在我要抓取在华中科技大学举办的宣讲会的信息,网页如下图:



    查看网页源代码,如下图:


    可以看出,公司名是在一个 company 标签内,宣讲会时间是在一个类名为 text-center 的 td 标签内,学校的具体地点则是在一个类名为 preach-tbody-addre 的 td 标签内。这么一分析,要提取华中科技大学的宣讲会信息就变得挺简单了。

    Java代码如下:

    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;
    
    public class Main {
        public static void main(String[] args) throws IOException {
            String url = "http://xjh.haitou.cc/wh/uni-1/after/hold/page-1/";
            Connection conn = Jsoup.connect(url);
            // 修改http包中的header,伪装成浏览器进行抓取
            conn.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/    20100101 Firefox/32.0");
            Document doc = conn.get();
            
            // 获取tbody元素下的所有tr元素
            Elements elements = doc.select("tbody tr");
            for(Element element : elements) {
            	String companyName = element.getElementsByTag("company").text();
            	String time = element.select("td.text-center").first().text();
            	String address = element.getElementsByClass("preach-tbody-addre").text();
            	
            	System.out.println("公司:"+companyName);
            	System.out.println("宣讲时间:"+time);
            	System.out.println("宣讲学校:华中科技大学");
            	System.out.println("具体地点:"+address);
            	System.out.println("---------------------------------");
            }
        }
    }

    某些网站禁止爬虫,不能抓取或者抓取一定数量后封IP。这时候我们需要伪装成浏览器进行抓取,这可以通过修改http包中的header来实现(设置User-Agent)。运行上面的程序得到输出结果:

    公司:瑞声科技(常州)有限公司
    宣讲时间:2015-03-07 19:00(周六)
    宣讲学校:华中科技大学
    具体地点:大学生活动中心305阶梯教室
    ---------------------------------
    公司:普联技术有限公司
    宣讲时间:2015-03-08 19:00(周日)
    宣讲学校:华中科技大学
    具体地点:大学生活动中心305阶梯教室
    ---------------------------------
    公司:大联大投资控股股份有限公司
    宣讲时间:2015-03-09 09:30(周一)
    宣讲学校:华中科技大学
    具体地点:大学生活动中心305阶梯教室
    ---------------------------------
    ......


    三、应用到Android程序中

    开发 Android 程序,你需要搭建开发环境,很简单:先安装Java的JDK(最好不低于1.6),然后去Android官网下载并安装 Android Studio 就行了。

    在Android程序中使用 Jsoup 需要注意两点:

    • 在AndroidManifest.xml文件中添加网络访问权限android.permission.INTERNET

    • Android在4.0之后,不允许在主线程里执行网络(http)请求,也就是说 Jsoup 的代码需要写在子线程里。

    1) 多线程

    4.0 版本以后,如果你在主线程里尝试进行网络操作,会报android.os.NetworkOnMainThreadException 的异常。所以我们需要开辟子线程进行异步加载,用到ThreadRunnableHandler这三个类:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.share_mblog_view);
        // 开辟一个线程
        new Thread(runnable).start();
    }
    
    Runnable runnable = new Runnable(){
        @Override
        public void run() {
        	/**
             * 要执行的操作
             */
        	// 执行完毕后给handler发送一个空消息
            handler.sendEmptyMessage(0);
        }
    }
    
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            /**
             * 处理UI
             */
        	// 当收到消息时就会执行这个方法
        }
    }

    2) 判断网络连接是否可用

    如果在没有可用网络的情况下执行网络爬虫程序,App将会报错。所以在每次执行之前都应该先判断网络是否可用。大致步骤如下:

    ① 获取ConnectivityManager对象

    Context context = activity.getApplicationContext();
    // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
    ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    ② 获取NetworkInfo对象

    NetworkInfo info = cm.getActiveNetworkInfo();
    ③ 判断网络类型,Android的网络分为两大类:WIFI 和 手机网络

    // WIFI 判定条件
    info != null && info.getType() == ConnectivityManager.TYPE_WIFI
    // 手机网络 判定条件
    info !=null && info.getType() ==  ConnectivityManager.TYPE_MOBILE

    而手机网络具体又分为很多类,比如移动3G、移动2G、联通2G等等。这里就不说了,自行Google。

    ④ 判断网络连接是否可用(包括所有网络类型)

    public boolean isNetworkAvailable(Activity activity)
    {
        Context context = activity.getApplicationContext();
        ConnectivityManager cm = (ConnectivityManager) 
        		context.getSystemService(Context.CONNECTIVITY_SERVICE);
    
        if (cm == null)
            return false;
        else
        {   // 获取所有NetworkInfo对象
            NetworkInfo[] networkInfo = cm.getAllNetworkInfo();
            if (networkInfo != null && networkInfo.length > 0)
            {
                for (int i = 0; i < networkInfo.length; i++)
                    if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED)
                        return true;  // 存在可用的网络连接
            }
        }
        return false;
    }
    注意,上述操作需要在 AndroidManifest.xml 文件中添加访问网络状态的权限:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


    另外,本程序在 UI 界面开发上涉及到 Android 中的 ListView(显示)、PopupWindow(菜单)、ProgressDialog(加载)、AlertDialog(提示)等控件的使用。因为本文并不是讨论 Android 控件的使用,在这里就不赘述了。

    源码下载:https://github.com/SongLee24/android-crawler




    个人站点:http://songlee24.github.com






    展开全文
  • Android网络爬虫

    2018-09-18 20:29:31
    我用的是嗅事百科做的例子 ... 打开嗅事百科 按 f12 查看源码 我对网页了解也不是太多,在网上查了一些资料,然后就开始上手了,对于网址的处理可以使用开源库,我使用了Jsoup 首先添加依赖库implementation 'org....

    GitHub

    我用的是嗅事百科做的例子

    这里我把网页趴下来,然后用了一个listview展示出来,实现了刷新,加载更多,还有点击事件

    在这里插入图片描述
    打开嗅事百科 按 f12 查看源码

    在这里插入图片描述

    我对网页了解也不是太多,在网上查了一些资料,然后就开始上手了,对于网址的处理可以使用开源库,我使用了Jsoup
    首先添加依赖库implementation 'org.jsoup:jsoup:1.11.3'
    具体的内容请查看Jsoup
    下面看我的主活动
    很显然我首先调用了方法
    init((++id) % 13);
    参数其实不重要,这是我为了给listview刷新用的,因为我发现嗅事百科的下一页内容就是网址里面的一个数字加了一,但是最多十三页,所以我就取余了,看这个方法,实际上是另开了一个线程去进行网络请求,当请求完后就通知Handler更新UI,最初做的时候,我切换线程加载HTML后,不知道该如何处理网络请求和UI更新,因为,当网络请求没有结束时是不能更新UI的,就算是更新了但也存在一个问题,我在这个线程请求网络,如果适配器不为空了便可以更新UI了,但是更新完后,网络请求的这个线程还没结束,所以适配器内容就和UI上显示的不一样,然后你要是处理listview的点击事件就会崩掉,最后我使用了Handler,我让线程去进行网络请求,当线程结束时再通知Handler进行UI更新。

    方法里面
    Jsoup.connect();
    是为了把源码解析出来
    document.select(“a.contentHerf”);
    可以由我截图圈的发现正文正是a.contentHerf下的 ,所以把他当做条件筛选即可,然后会返回多个数据,逐个遍历即可,看代码里面的循环
    element.text() 便是得到正文部分了
    另外一个
    element.attr(“href”) 是筛选href下的内容了,这个是什么呢
    我们把嗅事百科这个正文点击一下进入详情页,观察网址,是不是
    https://www.qiushibaike.com+href呢?之所以弄这个原因是有的文章太长,不能一次性显示完,所以就要进入详情页继续爬,我这里的实现是点击点击这个listview子项就重新启动一个活动,访问这个详情页的网址,然后展示出来,其实这个网页里面还会有图片,或者视频,大家看我圈的一个内容,src便签下的东西便是图片的地址了,大家可以自行拓展,把这些视频图片和头像都可以趴下来,展示出来,还有一个要说的事适配器的Thing这个有两个成员变量,一个是解析出的正文,还有就是详情页的地址了,地址传给另一个活动,即可把所有的内容爬下来。

    当然,我用了SmartRefreshLayout 实现了炫酷的刷新,还有卡片布局,详细内容大家有兴趣的可以查一查,下面附上代码

    主活动 Mainactivity

    public class MainActivity extends AppCompatActivity {
    
        private SmartRefreshLayout smartRefreshLayout;
        private String TAG = "MainActivity";
        private List<Thing> things = new ArrayList<>();
        ListView listView;
        XiuAdapter adapter;
        private int id = 0;
        private Handler handler;
    
        @SuppressLint("HandlerLeak")
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            listView = findViewById(R.id.xiuShi);
            smartRefreshLayout = findViewById(R.id.smart_layout);
            smartRefreshLayout.setEnableRefresh(true);//启用刷新
            smartRefreshLayout.setEnableLoadmore(true);//启用加载
            init((++id) % 13);
    
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == 111) {
                        adapter = new XiuAdapter(MainActivity.this, R.layout.thing_item, things);
                        listView.setAdapter(adapter);
                    }
                }
            };
    
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Thing thing = things.get(position);
                    Intent intent = new Intent(MainActivity.this, ContentActivity.class);
                    intent.putExtra("url", thing.getAddress());
                    startActivity(intent);
                }
            });
    
            smartRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
                @Override
                public void onRefresh(RefreshLayout refreshlayout) {
                    refresh((++id) % 13);
                }
            });
    
            smartRefreshLayout.setOnLoadmoreListener(new OnLoadmoreListener() {
                @Override
                public void onLoadmore(RefreshLayout refreshlayout) {
                    moreContent((++id) % 13);
                }
            });
        }
    
        private void moreContent(int i) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Document document = Jsoup.connect(
                                "https://www.qiushibaike.com/8hr/page/" + id + "/").get();
                        Elements elements = document.select("a.contentHerf");
                        for (int i = 0; i < elements.size(); i++) {
                            Element element = elements.get(i);
                            Thing thing = new Thing("        " + element.text() + "",
                                    "https://www.qiushibaike.com" + element.attr("href"));
                            things.add(thing);
                        }
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                adapter.notifyDataSetChanged();
                                smartRefreshLayout.finishLoadmore();
                            }
                        });
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        private void refresh(final int id) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        things.clear();
                        Document document = Jsoup.connect(
                                "https://www.qiushibaike.com/8hr/page/" + id + "/").get();
                        Elements elements = document.select("a.contentHerf");
                        for (int i = 0; i < elements.size(); i++) {
                            Element element = elements.get(i);
                            Thing thing = new Thing("        " + element.text() + "",
                                    "https://www.qiushibaike.com" + element.attr("href"));
                            things.add(thing);
                        }
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                adapter.notifyDataSetChanged();
                                smartRefreshLayout.finishRefresh();
                            }
                        });
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        private void init(final int id) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Log.d("HTML", "-----------------------");
                        Document document = Jsoup.connect("https://www.qiushibaike.com/8hr/page/" + id + "/").get();
                        Elements elements = document.select("a.contentHerf");
                        for (int i = 0; i < elements.size(); i++) {
                            Element element = elements.get(i);
                            Thing thing = new Thing("        " + element.text() + "",
                                    "https://www.qiushibaike.com" + element.attr("href"));
                            things.add(thing);
                            Log.d("HTML", thing.getAddress());
                            Log.d("HTML", element.text());
                        }
    
                        Log.d("HTML", "-----------------------");
                        Message msg = new Message();
                        msg.what = 111;
                        handler.sendMessage(msg);
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
    

    Thing类

    package com.example.webspider;
    
    public class Thing {
    
        public Thing(String item, String address) {
            this.item = item;
            this.address = address;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        private String item;
    
        private String address;
    
        public void setItem(String item) {
            this.item = item;
        }
    
        public String getItem() {
    
            return item;
        }
    }
    

    适配器

    package com.example.webspider;
    
    import android.content.Context;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.TextView;
    
    import java.util.List;
    
    public class XiuAdapter extends ArrayAdapter<Thing> {
    
        private int id;
    
        public XiuAdapter(@NonNull Context context, int resource, @NonNull List<Thing> objects) {
            super(context, resource, objects);
            id = resource;
        }
    
        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            View view = LayoutInflater.from(getContext()).inflate(id, parent, false);
            Thing thing = getItem(position);
            TextView textView = view.findViewById(R.id.thing_name);
            textView.setText(thing.getItem());
            return view;
        }
    }
    
    

    详细内容的活动

    package com.example.webspider;
    
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.TextView;
    
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    
    import java.io.IOException;
    
    public class ContentActivity extends AppCompatActivity {
    
        private String url;
    
        private String content = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_content);
            final TextView textView = findViewById(R.id.content_thing);
            url = getIntent().getStringExtra("url");
    
            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == 111) {
                        textView.setText("        " + msg.obj.toString());
                    }
                }
            };
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Document document = Jsoup.connect(url).get();
                        Elements elements = document.select("div.content");
                        for (int i = 0; i < elements.size(); i++) {
                            Element element = elements.get(i);
                            Log.d("wds", element.text());
                            Message msg = new Message();
                            msg.obj = element.text();
                            msg.what = 111;
                            handler.sendMessage(msg);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    
    
        }
    
    
    }
    
    

    主活动布局

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.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">
    
        <com.scwang.smartrefresh.layout.SmartRefreshLayout
            android:id="@+id/smart_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:srlAccentColor="#00000000"
            app:srlEnablePreviewInEditMode="true"
            app:srlPrimaryColor="#00000000">
    
            <ListView
                android:id="@+id/xiuShi"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginLeft="20dp"
                android:layout_marginRight="20dp"
                >
    
            </ListView>
        </com.scwang.smartrefresh.layout.SmartRefreshLayout>
    
    
    </android.support.constraint.ConstraintLayout>
    

    详细内容布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    
        tools:context=".ContentActivity">
    
        <ScrollView xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="20dp">
    
    
            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="20dp"
                app:cardUseCompatPadding="true"
                app:cardCornerRadius="10dp"
                app:cardBackgroundColor="#FFF8DC">
    
                <TextView
                    android:id="@+id/content_thing"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp" />
    
            </android.support.v7.widget.CardView>
        </ScrollView>
    
    </LinearLayout>
    

    listview的内容

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.CardView 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="wrap_content"
        android:layout_margin="10dp"
        android:layout_marginTop="10dp"
        app:cardBackgroundColor="#FFF8DC"
        app:cardCornerRadius="10dp"
        app:cardUseCompatPadding="true">
    
        <TextView
            android:id="@+id/thing_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp" />
    
    </android.support.v7.widget.CardView>
    

    还有SmartRefreshLayout和CardView的依赖库

        implementation 'com.android.support:cardview-v7:28.0.0-rc02'
        implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4-7'
        implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.4-7'
    

    最后记得加上联网权限

    <uses-permission android:name="android.permission.INTERNET" />
    
    展开全文
  • 这几天写了一个Android上面简单的爬虫Demo 数据爬取完后通过RecyclerView展示,这篇文章先写爬取数据部分 这里我爬虫测试网站是:什么值得买 想要爬取的数据是首页的一些精选文章,主要爬取文章标题、图片、简介 这...

    这几天写了一个Android上面简单的爬虫Demo
    数据爬取完后通过RecyclerView展示,这篇文章先写爬取数据部分

    这里我爬虫测试网站是:什么值得买

    想要爬取的数据是首页的一些精选文章,主要爬取文章标题、图片、简介

    在这里插入图片描述

    这个是我爬到的数据
    在这里插入图片描述
    这里需要引用到Jsoup和OkHttp的jar包,我是下载下来,添加到项目工程当中
    在这里插入图片描述
    也可以直接在gradle文件当中配置

    implementation 'org.jsoup:jsoup:1.11.3'
    implementation 'com.squareup.okhttp3:okhttp:3.4.1'
    

    然后就可以开始写代码爬虫啦

    实体类Article.java

    /*
     *@Author:Swallow
     *@Date:2019/3/21
     * 抓取到的文章数据封装
     */
    public class Article {
        private String title;
        private String author;
        private String imgUrl;
        private String context;
        private String articleUrl;
        private String date;
        private String from;
    
    //有几个属性还没用到,所以构造方法先用上这四个有爬取到数据的
        public Article(String title, String author, String imgUrl, String context) {
            this.title = title;
            this.author = author;
            this.imgUrl = imgUrl;
            this.context = context;
        }
    
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public String getImgUrl() {
            return imgUrl;
        }
    
        public void setImgUrl(String imgUrl) {
            this.imgUrl = imgUrl;
        }
    
        public String getContext() {
            return context;
        }
    
        public void setContext(String context) {
            this.context = context;
        }
    
        public String getArticleUrl() {
            return articleUrl;
        }
    
        public void setArticleUrl(String articleUrl) {
            this.articleUrl = articleUrl;
        }
    
        public String getDate() {
            return date;
        }
    
        public void setDate(String date) {
            this.date = date;
        }
    
        public String getFrom() {
            return from;
        }
    
        public void setFrom(String from) {
            this.from = from;
        }
    
        @Override
        public String toString() {
            return "Article{" +
                    "title='" + title + '\'' +
                    ", author='" + author + '\'' +
                    ", imgUrl='" + imgUrl + '\'' +
                    ", context='" + context + '\'' +
                    ", articleUrl='" + articleUrl + '\'' +
                    ", date='" + date + '\'' +
                    ", from='" + from + '\'' +
                    '}';
        }
    }
    
    

    OkHttp请求网络

    
    /*
     *@Author:Swallow
     *@Date:2019/3/7
     */
    public class OkHttpUtils {
        public static String OkGetArt(String url) {
            String html = null;
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(url)
                    .build();
            try (Response response = client.newCall(request).execute()) {
                //return
                html = response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return html;
        }
       }
    

    抓取数据的类
    这里用到Jsoup,它主要是解析获取到的网页资源的HTML标签来抓取里面的数据
    这里我们可以到原本的网址上去查看网页源码,就可以看到网页的结构,还有要获取的数据所对应的标签

    在这里插入图片描述

    /*
     *@Author:Swallow
     *@Date:2019/3/21
     */
    public class GetData {
    /**
         * 抓取什么值得买首页的精选文章
         * @param html
         * @return  ArrayList<Article> articles
         */
        public static ArrayList<Article> spiderArticle(String html){
            ArrayList<Article> articles = new ArrayList<>();
    
                Document document = Jsoup.parse(html);
                Elements elements = document
                        .select("ul[class=feed-list-hits]")
                        .select("li[class=feed-row-wide J_feed_za ]");
                for (Element element : elements) {
                    String title = element
                            .select("h5[class=feed-block-title]")
                            .text();
                    String author = element
                            .select("div[class=feed-block-info]")
                            .select("span")
                            .text();
    
                    String imgurl = element
                            .select("div[class=z-feed-img]")
                            .select("a")
                            .select("img")
                            .attr("src");
                    String context = element
                            .select("div[class=feed-block-descripe]")
                            .text();
                    String url = element
                            .select("div[class=feed-block z-hor-feed ]")
                            .select("a")
                            .attr("href");
    
                    Article article = new Article(title,author,imgurl,context);
                    articles.add(article);
                    Log.e("DATA>>",article.toString());
                }
            return articles;
        }
    }
    

    后面直接调用方法就可以
    这里要注意一点就是,Android上面发送网络请求要放到子线程当中,所以调用的时候需要开启一个新的子线程

    final String url = "https://www.smzdm.com/";
            new Thread(){
                public void run(){
                    String html = OkHttpUtils.OkGetArt(url);
                    ArrayList<Article> articles = GetData.spiderArticle(html);
                    //发送信息给handler用于更新UI界面
                    Message message = handler.obtainMessage();
                    message.what = 1;
                    message.obj = articles;
                    handler.sendMessage(message);
                }
            }.start();
    
    展开全文
  • android爬虫

    2018-07-27 11:54:39
    方式有多种,今天讲讲android的一个爬虫框架Jsoup.按照官网介绍-&gt;jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作...
  • 网络爬虫 网络爬虫(web crawler), 以前经常称为网络蜘蛛(spider), 是按照一定的规则自动浏览万维网并获取信息的机器人程序(或叫脚本), 曾经被广泛的应用于互联网搜索引擎. 使用过互联网和浏览器的人都知道, 网页中...
  • android studio 爬虫 工程

    2020-07-30 23:32:12
    android studio 爬虫程序,爬取小说目录http://www.aiquxs.com/read/41/41742/index.html 并将目录显示到listview中 其中含包含了webview跳转不调用系统浏览器的代码
  • Python网络爬虫实战

    2019-01-16 11:15:55
    网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动的抓取信息的程序或者脚本。 网络爬虫是互联网上进行信息采集的通用手段,在互联网的各个专业方向上都是不可或缺的底层技术支撑。本课程从...
  • 简介:Android 本地网络小说爬虫,基于 jsoup 及 xpath 更多:作者 提 Bug  标签:   Android 本地网络小说爬虫,基于 jsoup 与 xpath,通过模版解析网页。 支持书源 模版示例 调用方式 ScreenShot 支持...
  • 网络爬虫入门学习

    2019-03-30 19:41:12
    突然对网络爬虫产生了一些兴趣 (鬼知道是因为什么) ,就在网络找到了些学习资料,花了半个月的时间进行了一个网络爬虫入门学习,当然这种学习要结合实践啦。 Talk is cheap, show me the code! 所以特意将半...
  • Android实战——jsoup实现网络爬虫,爬糗事百科主界面 本篇文章包括以下内容: 前言 jsoup的简介 jsoup的配置 jsoup的使用 结语 前言对于Android初学者想要做项目时,最大的烦恼是什么?毫无疑问是数据...
  • Jsoup这个问题说实话困扰了我很久,其实我们先用Java把它写出来,会更加的容易理解。 ... 大家先导入jsoup库 ...我先用eclipse给大家先用java写一篇,之后我会教大家如何抓取网络数据后放入Listview中。 我们...
  • Android网页爬虫

    2017-03-03 17:34:29
    静态页面 需求:获取http://blog.csdn.net/yhaolpz?viewmode=contents页面的title 首先通过okhttp以get方式请求页面: final String url = ... Request request = new Request.B
  • 一、浅谈网络爬虫 ​随着网络的迅速发展,互联网成为大量信息的载体,如何有效的利用这些信息成为巨大的挑战。区别于搜索引擎,定向抓取相关网页资源的网络爬虫应用而生,可以根据既定的抓取目标有效的选择网络上需要...
  • 本套视频课程的讲师刘硕是清华大学出版社出版的《精通Scrapy网络爬虫》的作者,该视频课程为此书的配套课程, 在书中内容的基础上增加、修改了部分实战案例。《精通Scrapy网络爬虫》以应用为出发点,详细深入地介绍...
  • 首先选择的是htmlunit解析登录界面html,一开始在pc上测的能实现,结果在android上运行不起来,因为htmlunit利用了javax中的类实现完成解析,android不支持javax,所以就跑不起来。 不过pc还是ok的package ...
  • 比如我在第一个网页获取新闻标题和新闻链接,怎么在链接中在获取图片和内容,目标Android开发,是异步中在异步吗?能给一段代码实例吗? 我创建了一个新闻实体类,难道我在异步中获取标题,还在开一个异步吗??? ...
  • 自己在网页爬取这一块怎么一个“菜”字了得,唉,对自己也是无语了!经过几次的折磨,对网页爬虫以及用到的json技术有了大致的了解,故作一总结,供有同样迷惑的朋友参考学习。
  • @冰蓝  之前在北京买房,谁想房价开始疯长,链家的...上次发现Android QQ和iOS QQ可以显示网络状态(2G/WiFi)之后,突然想到,这样子好像可以监视某人的出行和作息规律。简单的来说,在家里或者工作的地方,一般是有
  • 网络爬虫定义 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。 可以更形象的理解:网络相当于一个巨大的蜘蛛网,...
1 2 3 4 5 ... 20
收藏数 7,501
精华内容 3,000
关键字:

动态网络爬虫android