gpt4 book ai didi

JAVA 多线程爬虫实例详解

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章JAVA 多线程爬虫实例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

JAVA 多线程爬虫实例详解 。

前言 。

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

线程 。

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

runnable接口 。

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

Thread类 。

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

synchronized关键字 。

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

利用加锁同步 。

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

线程池 。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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());
   }
}

代码分析 。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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);
   }
}

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

原文链接:http://blog.csdn.net/qq_30843221/article/details/52486735 。

最后此篇关于JAVA 多线程爬虫实例详解的文章就讲到这里了,如果你想了解更多关于JAVA 多线程爬虫实例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com