老李分享:网页爬虫java实现

 

poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-84505200。

一. 设计思路

 

(1)一个收集所需网页全站或者指定子域名的链接队列

(2)一个存放将要访问的URL队列(跟上述有点重复, 用空间换时间, 提升爬取速度)

(3)一个保存已访问过URL的数据结构

数据结构有了, 接下来就是算法了, 一般推荐采取广度优先的爬取算法, 免得中了反爬虫的某些循环无限深度的陷阱。

使用了 jsoup (一个解析HTML元素的Lib)和 httpclient (网络请求包)来简化代码实现。

二. 代码实现

上述三种数据结构:

// 已爬取URL <URL, isAccess>
final static ConcurrentHashMap<String, Boolean> urlQueue = new ConcurrentHashMap<String, Boolean>();

// 待爬取URL
final static ConcurrentLinkedDeque<String> urlWaitingQueue = new ConcurrentLinkedDeque<String>();

// 待扫描网页URL队列
final static ConcurrentLinkedDeque<String> urlWaitingScanQueue = new ConcurrentLinkedDeque<String>();

入队等待:

/**

* url store in the waiting queue

* @param originalUrl

* @throws Exception

*/

private static void enterWaitingQueue(final String originalUrl) throws Exception{

String url = urlWaitingScanQueue.poll();

// if accessed, ignore the url

/*while (urlQueue.containsKey(url)) {

url = urlWaitingQueue.poll();

}*/

final String finalUrl = url;

Thread.sleep(600);

new Thread(new Runnable() {

public void run() {

try{

if (finalUrl != null) {

Connection conn = Jsoup.connect(finalUrl);

Document doc = conn.get();

//urlQueue.putIfAbsent(finalUrl, Boolean.TRUE); // accessed

logger.info("扫描网页URL: " + finalUrl);

Elements links = doc.select("a[href]");

for (int linkNum = 0; linkNum < links.size(); linkNum++) {

Element element = links.get(linkNum);

String suburl = element.attr("href");

// 某条件下, 并且原来没访问过

if (!urlQueue.containsKey(suburl)) {

urlWaitingScanQueue.offer(suburl);

urlWaitingQueue.offer(suburl);

logger.info("URL入队等待" + linkNum + ": " + suburl);

}

}

}

}

} catch (Exception ee) {

logger.error("muti thread executing error, url: " + finalUrl, ee);

}

}

}).start();

}

访问页面:

private static void viewPages() throws Exception{

Thread.sleep(500);

new Thread(new Runnable() {

@Override

public void run() {

try {

while(!urlWaitingQueue.isEmpty()) {

String url = urlWaitingQueue.peek();

final String finalUrl = url;

// build a client, like open a browser

CloseableHttpClient httpClient = HttpClients.createDefault();

// create get method, like input url in the browser

//HttpGet httpGet = new HttpGet("http://www.dxy.cn");

HttpPost httpPost = new HttpPost(finalUrl);

StringBuffer stringBuffer = new StringBuffer();

HttpResponse response;

//List<NameValuePair> keyValue = new ArrayList<NameValuePair>();

//  Post parameter

//            keyValue.add(new BasicNameValuePair("username", "zhu"));

//

//            httpPost.setEntity(new UrlEncodedFormEntity(keyValue, "UTF-8"));

// access and get response

response = httpClient.execute(httpPost);

// record access URL

urlQueue.putIfAbsent(finalUrl, Boolean.TRUE);

if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

HttpEntity httpEntity = response.getEntity();

if (httpEntity != null) {

logger.info("viewPages访问URL:" + finalUrl);

BufferedReader reader = new BufferedReader(

new InputStreamReader(httpEntity.getContent(), "UTF-8"));

String line = null;

if (httpEntity.getContentLength() > 0) {

stringBuffer = new StringBuffer((int) httpEntity.getContentLength());

while ((line = reader.readLine()) != null) {

stringBuffer.append(line);

}

System.out.println(finalUrl + "内容: " + stringBuffer);

}

}

}

}

} catch (Exception e) {

logger.error("view pages error", e);

}

}

}).start();

}

三. 总结及将来要实现功能

以上贴出了简易版Java爬虫的核心实现模块, 基本上拿起来就能测试。

控制爬取速度(调度模块), 使用代理IP访问(收集网络代理模块)的实现在你可以在自己的版本中会慢慢加上...

老李分享:网页爬虫java实现的更多相关文章

  1. 老李分享:《Java Performance》笔记1——性能分析基础 1

    老李分享:<Java Performance>笔记1——性能分析基础   1.性能分析两种方法: (1).自顶向下: 应用开发人员通过着眼于软件栈顶层的应用,从上往下寻找性能优化的机会. ...

  2. 网页爬虫的设计与实现(Java版)

    网页爬虫的设计与实现(Java版)     最近为了练手而且对网页爬虫也挺感兴趣,决定自己写一个网页爬虫程序. 首先看看爬虫都应该有哪些功能. 内容来自(http://www.ibm.com/deve ...

  3. POPTEST老李分享DOM解析XML之java

    POPTEST老李分享DOM解析XML之java   Java提供了两种XML解析器:树型解释器DOM(Document Object Model,文档对象模型),和流机制解析器SAX(Simple ...

  4. 老李分享:loadrunner的java user脚本开发

    老李分享:loadrunner的java user脚本开发 poptest在性能测试loadrunner的课程里,以web协议为主,同时也讲解其他协议的脚本开发,对于一个性能测试工程师需要掌握一个以上 ...

  5. 老李案例分享:定位JAVA内存溢出

    老李案例分享:定位JAVA内存溢出   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loadrunner的培 ...

  6. java实现网页爬虫

    接着上面一篇对爬虫需要的java知识,这一篇目的就是在于网页爬虫的实现,对数据的获取,以便分析. -----> 目录:   1.爬虫原理 2.本地文件数据提取及分析 3.单网页数据的读取 4.运 ...

  7. JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫

    JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...

  8. Java正则表达式--网页爬虫

    网页爬虫:其实就一个程序用于在互联网中获取符合指定规则的数据 爬取邮箱地址,爬取的源不同,本地爬取或者是网络爬取 (1)爬取本地数据: public static List<String> ...

  9. Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱(转)

    原文:http://www.52nlp.cn/python-网页爬虫-文本处理-科学计算-机器学习-数据挖掘 曾经因为NLTK的缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然开 ...

随机推荐

  1. FTPS (FTP over SSL) vs. SFTP (SSH 文件传输协议): 我们如何做出选择

    第一个RFC的FTP协议发布通过网络使用FTP协议(由RFC 959或更高版本)的文件传输始于1980年,FTP提供上传,下载和删除文件,创建和删除目录,读取目录内容的功能.虽然FTP是非常受欢迎的, ...

  2. 蔡勒(Zeller)公式:根据日期推算是星期几

    Zeller's Congruence: w=y + [y/4] + [c/4] - 2c + [26(m+1)/10] + d - 1 公式中的符号含义如下:w:星期: w对7取模得:0-星期日,1 ...

  3. 华为HG8245 电信 光猫破解获取超级密码

    这款光猫是 猫+无线路由器一体的 默认没有打开路由功能.  光猫背后的用户名和密码是有限制的没人什么用处,如果要打开路由功能就得要有 超级用户名和密码 不然就算收的到无线连的起也上不了网 .这时就需要 ...

  4. mysql 命令备份

    导出要用到MySQL的mysqldump工具,基本用法是:    shell> mysqldump [OPTIONS] database [tables]    如果你不给定任何表,整个数据库将 ...

  5. 每天一个Linux命令(12)--more命令

    more命令,功能类似cat,  cat 命令是这个文件的内容从上到下显示在屏幕上,more会以一页一页的显示方便使用者主页阅读,而最基本的指令就是按空格键就往下一页显示,按B键就会往回一页显示,而且 ...

  6. 原生js和jquery实现图片轮播特效(转)

    本文给大家分享的是使用原生JS和JQ两种方法分别实现相同的图片轮播特效,十分的实用,也非常方便大家对比学习原生js和jQuery,有需要的小伙伴可以参考下. 1)首先是页面的结构部分对于我这种左右切换 ...

  7. WinSCP 中普通用户以 root 身份登录 Linux

    版本说明: Windows 10 CentOS 7 WinSCP 5.7.7 (Build 6257) 问题背景 使用 WinSCP 登录 CentOS 上传文件,使用的是普通用户,且已加入 sudo ...

  8. tp框架基础(详细步骤分解,易懂)下

    在浏览器中如果要访问操作方法的时候以什么方式来访问 有四种方式 第一种是get方式,第二种是访问路径 这四种方式我们可以通过修改配置文件来改掉url的模式 我们需要来改一下我们的配置文件 在这个路径下 ...

  9. 【Ruby on Rails】Model中关于保存之前的原值和修改状态

    今天在Rails的Model中遇到了一个问题—— 当我从Model类中获取了一个ActiveRecord对象,对其进行了一系列修改(尚未保存),我该如何确定究竟哪些修改了呢? (设Model为Opti ...

  10. conky 1.10以后的新配置格式

    包装 config conky.config = { ... } 包装 TEXT conky.text = [[ ... ]] 每个 config 选项的变量和取值之间插入 "=" ...