• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > JAVA 多线程爬虫实例详解

JAVA 多线程爬虫实例详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了java多线程爬虫,java 爬虫,网络爬虫java,java爬虫代码,网络爬虫代码 java等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

JAVA 多线程爬虫实例详解

前言

以前喜欢Python的爬虫是出于他的简洁,但到了后期需要更快,更大规模的爬虫的时候,我才渐渐意识到Java的强大。Java有一个很好的机制,就是多线程。而且Java的代码效率执行起来要比python快很多。这份博客主要用于记录我对多线程爬虫的实践理解。

线程

线程是指一个任务从头至尾的执行流。线程提供了运行一个任务的机制。对于Java而言,可以在一个程序中并发地启动多个线程。这些线程可以在多处理器系统上同时运行。

runnable接口

任务类必须实现runnable接口,它只包含一个run方法。需要实现这个方法来告诉系统线程将如何运行。

Thread类

包含为任务而创建的线程的构造方法,以及控制线程的方法。

synchronized关键字

为避免竞争状态,防止多个线程同时进入程序的某个特定部分,即临界区,以便一次只有一个线程可以访问临界区。

利用加锁同步

Java可以显式加锁,一个锁是一个Lock接口的实例,它定义了加锁和释放锁的方法。

线程池

线程池是管理开发执行任务个数的理想方法。Java提供Executor接口来执行线程池中的任务,提供ExecutorService接口管理和控制任务。

使用线程池的方法获取url列表

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
 * 获取京东评论url列表
 */

public class MyThreading {
  private static String p_id = null;
  private static Url urls = null;

  public MyThreading(String p_id){
    this.p_id = p_id ;   // 京东商品的id
    urls = new Url(p_id); 
  }

  public List<String> getUriList(){
    ExecutorService executor = Executors.newCachedThreadPool();
    for (int i = 0 ; i < 600 ; i ++){
      executor.execute(new AddUrl(i));    // 添加任务到线程池
    }
    executor.shutdown();
    while (!executor.isTerminated()){}
    return urls.getList();
  }

  public static class AddUrl implements Runnable{
    int page;
    public AddUrl(int page){
      this.page = page;
    }
    public void run(){
      urls.addList(page);   // 启动多线程任务
    }
  }

  public static class Url {

    private static Lock lock = new ReentrantLock();     // 开启显式家锁
    private static List<String> urlList = new ArrayList();     
    private String p_id;

    public Url(String p_id ){
      this.p_id = p_id ;
    }
    public List<String> getList(){
      return urlList;
    }
    public void addList(int page){
      lock.lock();
      try{
        String url = "http://club.jd.com/productpage/p-" + p_id + "-s-0-t-0-p-" + String.valueOf(page) + ".html";
//       Thread.sleep(5);
        urlList.add(url);    //添加url到url列表
      }catch(Exception ex ){
      }
      finally {
        lock.unlock();     // 解锁
      }

    }
  }
  public static void main(String[] args) {
    String p_id = "2441288";
    MyThreading myThreading = new MyThreading(p_id);
    List <String> urlList = myThreading.getUriList();
    for(String url : urlList){
      System.out.println(url);
    }
    System.out.println(urlList.size());
  }
}

</div>

代码分析

  • 代码的作用:获取京东评论的url列表
  • 类的说明:MyThreading是主类, AddUrl和Url是它的内部类,AddUrl实现了runnable的接口,主要启动多线程服务运行Url的addList方法。而Url是最内核的部分 ,他提供addList任务和多线程的共享区域urlList,所以在实现添加url的步骤中,需要对urlList加锁。
  • 线程池主要有两种类型,一个是固定线程池,即newFixedThreadPool;另一个是newCachedThreadPool,这个主要利用了缓冲机制,能动态地添加线程。在上述代码中,我主要使用了newCachedthreadPool.

使用线程池的方法根据url列表爬取网页元素

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class ThreadingCrawel {
  private static Content content = null;
  private static List<String> urlList = null;

  public ThreadingCrawel(List<String> urlList){
    this.urlList = urlList;
    content = new Content();
  }
  public List<String> getContent(){

    ExecutorService executor = Executors.newCachedThreadPool();
    for (String url : urlList){
      executor.execute(new AddContent(url));
    }
    executor.shutdown();
    while(!executor.isTerminated()){}
    return content.getContent();

  }

  public static class AddContent implements Runnable{
    String url;
    public AddContent(String url){
      this.url = url;
    }
    public void run(){
      content.addContent(url);
    }
  }

  public static class Content {

    private static Lock lock = new ReentrantLock();
    private static List<String> contentList = new ArrayList();

    public void addContent(String url){

      String content = "";
      BufferedReader in = null;
      try{
        URL realUrl = new URL(url);
        URLConnection connection = realUrl.openConnection();
        in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "gbk"));
        String line;
        while( (line = in.readLine()) != null){
          content += line +"\n";
        }
      }catch(Exception e){
        e.printStackTrace();
      }
      finally{
        try{
          if (in != null){
            in.close();
          }
        }catch(Exception e2){
          e2.printStackTrace();
        }
      }

      Pattern p = Pattern.compile("content\":\".*?\"");
      Matcher match = p.matcher(content);
      String tmp;
       lock.lock();
      while(match.find()){
        tmp = match.group();
        tmp = tmp.replaceAll("\"", "");
        tmp = tmp.replace("content:", "");
        tmp = tmp.replaceAll("<.*?>", "");
        contentList.add(tmp);
        try {
          Thread.sleep(1);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
      lock.unlock();

    }
    public List getContent(){
      return contentList;
    }
  }
  public static void main(String[] args){
    long start = System.currentTimeMillis();
    String p_id = "2441288";
    MyThreading myThreading = new MyThreading(p_id);
    List <String> urlList = myThreading.getUriList();
    ThreadingCrawel threadingCrawel = new ThreadingCrawel(urlList);
    List <String> contentList = threadingCrawel.getContent();
    for(String content : contentList){
      System.out.println(content);
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);
  }
}

</div>

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JAVA 多线程爬虫实例详解
  • JAVA 多线程爬虫实例详解

相关文章

  • 2017-05-28MyBatis拦截器:给参数对象属性赋值的实例
  • 2017-05-28java算法导论之FloydWarshall算法实现代码
  • 2017-05-28Java 关键字static详解及实例代码
  • 2017-05-28javaweb判断当前请求是否为移动设备访问的方法
  • 2017-05-28java回调机制实例详解
  • 2017-05-28用java的spring实现一个简单的IOC容器示例代码
  • 2017-05-28java反射总结实例详解
  • 2017-05-28Java synchronized关键_动力节点Java学院整理
  • 2017-05-28springboot中thymeleaf模板使用详解
  • 2017-05-28Java中使用Jedis操作Redis的实现代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • spring boot如何使用spring AOP实现拦截器
    • Spring Boot集成MyBatis访问数据库的方法
    • springboot+EHcache 实现文章浏览量的缓存和超时更新
    • spring+hibernate 两种整合方式配置文件的方法
    • Java缓存池代码实例详解
    • Kotlin 与 Java基本语法对比
    • java poi解析word的方法
    • 浅析java修饰符访问权限(动力节点Java学院整理)
    • Kotlin教程之函数和包的定义和流程控制
    • 多线程死锁的产生以及如何避免死锁方法(详解)

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有