在Java Web爬虫中实现线程
这是我写的原始网络爬虫:(仅供参考) 这是一个简单的网络爬虫程序,它访问给定的初始网页,从该网页中删除所有链接,并将它们添加到队列(LinkedList),然后在队列中逐个弹出,每次访问一次,循环再次开始。为了加速我的程序,为了学习,我尝试使用线程来实现,这样我就可以让多个线程同时运行,在更短的时间内索引更多的页面。以下是每节课的内容: 主类 爬虫类(线程)在Java Web爬虫中实现线程,java,multithreading,concurrency,jsoup,web-crawler,Java,Multithreading,Concurrency,Jsoup,Web Crawler,这是我写的原始网络爬虫:(仅供参考) 这是一个简单的网络爬虫程序,它访问给定的初始网页,从该网页中删除所有链接,并将它们添加到队列(LinkedList),然后在队列中逐个弹出,每次访问一次,循环再次开始。为了加速我的程序,为了学习,我尝试使用线程来实现,这样我就可以让多个线程同时运行,在更短的时间内索引更多的页面。以下是每节课的内容: 主类 爬虫类(线程) 公共类爬虫程序扩展线程{ /**数据结构实例**/ 数据结构数据; /**程序终止前允许的页面连接数**/ 私有最终整数指数_限制=10;
公共类爬虫程序扩展线程{
/**数据结构实例**/
数据结构数据;
/**程序终止前允许的页面连接数**/
私有最终整数指数_限制=10;
/**要访问的初始URL**/
公共爬虫(数据结构d){
数据=d;
}
公开募捐{
//计数器以跟踪索引URL的数量
int计数器=0;
//当URL被留下来访问时
虽然((data.url_to_visit_size()>0)和&counter添加了:查看我的评论,我认为签入爬虫
// While URL's left to visit
while((data.url_to_visit_size() > 0) && counter<INDEX_LIMIT) {
//当URL被留下来访问时
while((data.url_to_visit_size()>0)和&counterclass控制器{
公共静态void main(字符串args[])引发InterruptedException{
最终整数限值=4;
List seedList=new ArrayList();//1
种子列表。添加(“https://www.youtube.com/");
种子列表。添加(“https://www.digg.com/");
种子列表。添加(“https://www.reddit.com/");
种子列表。添加(“https://www.nytimes.com/");
数据结构[]数据=新数据结构[限制];
对于(int i=0;i
你可以试试这个
创建种子列表
创建datastruc的对象并将种子列表添加到每个对象中
创建爬网数组并将datastruc对象逐个传递给它们
将爬网对象传递给执行器
以的形式提供当前用于多线程的实现,否则我们无法帮助您。在本网站中,通过外部链接提供代码是不可接受的。这个问题在这个时候会很奇怪,但您的CPU有多少内核?我的笔记本电脑是双核的,这可能取决于您与internet的连接。如果u是网络绑定的,那么有几个连接尝试使用连接可能会减慢速度。因为它至少有2个内核,所以每个线程将在一个内核中运行(假设您的操作系统能够很好地处理多线程,并且没有问题)。那么您的问题可能在于绑定到网络访问的I/O操作,正如@Jayde所指出的。使用此策略根本不需要使用任何并发列表。缺点是,当它们运行时,您不会获得太多实时反馈。第一句话是错误的,因为您可以使用并发列表为任务提供数据(以Runnable
或Callable
的形式)。第二句也是错误的,您只需为所有任务定义另一个共享的并发结构,其中每个任务都可以存储消息或信号或其他类型的信息。此外,如果您看到OP的实现,则在更改为线程池策略时,您不会获得太多速度。每个可调用对象都有一个要处理的URL,因此第一句是正确的例如,对于第二句话,是的,你可以为消息定义一个并发结构,但是,如果你不这样做,生活会更简单,但实时反馈会更少。然而,由于OP的爬虫确实相互作用,这种方法可能不太理想。
public class controller {
public static void main(String args[]) throws InterruptedException {
DataStruc data = new DataStruc("http://www.imdb.com/title/tt1045772/?ref_=nm_flmg_act_12");
Thread crawl1 = new Crawler(data);
Thread crawl2 = new Crawler(data);
crawl1.start();
crawl2.start();
}
}
public class Crawler extends Thread {
/** Instance of Data Structure **/
DataStruc data;
/** Number of page connections allowed before program terminates **/
private final int INDEX_LIMIT = 10;
/** Initial URL to visit **/
public Crawler(DataStruc d) {
data = d;
}
public void run() {
// Counter to keep track of number of indexed URLS
int counter = 0;
// While URL's left to visit
while((data.url_to_visit_size() > 0) && counter<INDEX_LIMIT) {
// Pop next URL to visit from stack
String currentUrl = data.getURL();
try {
// Fetch and parse HTML document
Document doc = Jsoup.connect(currentUrl)
.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36")
.referrer("http://www.google.com")
.timeout(12000)
.followRedirects(true)
.get();
// Increment counter if connection to web page succeeds
counter++;
/** .select returns a list of elements (links in this case) **/
Elements links = doc.select("a[href]"); // Relative URL
// Add newly found links to stack
addLinksToQueue(links);
} catch (IOException e) {
//e.printStackTrace();
System.out.println("Error: "+currentUrl);
}
}
}
public void addLinksToQueue(Elements el) {
// For each element in links
for(Element e : el) {
String theLink = e.attr("abs:href"); // 'abs' prefix ensures absolute url is returned rather then relative url ('www.reddit.com/hello' rather then '/hello')
if(theLink.startsWith("http") && !data.oldLink(theLink)) {
data.addURL(theLink);
data.addVisitedURL(theLink); // Register each unique URL to ensure it isnt stored in 'url_to_visit' again
System.out.println(theLink);
}
}
}
}
public class DataStruc {
/** Queue to store URL's, can be accessed by multiple threads **/
private ConcurrentLinkedQueue<String> url_to_visit = new ConcurrentLinkedQueue<String>();
/** ArrayList of visited URL's **/
private ArrayList<String> visited_url = new ArrayList<String>();
public DataStruc(String initial_url) {
url_to_visit.offer(initial_url);
}
// Method to add seed URL to queue
public void addURL(String url) {
url_to_visit.offer(url);
}
// Get URL at front of queue
public String getURL() {
return url_to_visit.poll();
}
// URL to visit size
public int url_to_visit_size() {
return url_to_visit.size();
}
// Add visited URL
public void addVisitedURL(String url) {
visited_url.add(url);
}
// Checks if link has already been visited
public boolean oldLink(String link) {
for(String s : visited_url) {
if(s.equals(link)) {
return true;
}
}
return false;
}
}
// While URL's left to visit
while((data.url_to_visit_size() > 0) && counter<INDEX_LIMIT) {
class controller {
public static void main(String args[]) throws InterruptedException {
final int LIMIT = 4;
List<String> seedList = new ArrayList<>(); //1
seedList.add("https://www.youtube.com/");
seedList.add("https://www.digg.com/");
seedList.add("https://www.reddit.com/");
seedList.add("https://www.nytimes.com/");
DataStruc[] data = new DataStruc[LIMIT];
for(int i = 0; i < LIMIT; i++){
data[i] = new DataStruc(seedList.get(i)); //2
}
ExecutorService es = Executors.newFixedThreadPool(LIMIT);
Crawler[] crawl = new Crawler[LIMIT];
for(int i = 0; i < LIMIT; i++){
crawl[i] = new Crawler(data[i]); //3
}
for(int i = 0; i < LIMIT; i++){
es.submit(crawl[i]) // 4
}
}
}