Java爬虫:使用Jvppeteer(Puppeteer)爬淘宝商品就这么简单?

Java爬虫:使用Jvppeteer(Puppeteer)爬淘宝商品就这么简单?

首页游戏大全流氓精英2地牢爬虫更新时间:2024-06-04

大家都知道,想要爬取某宝的商品,如果只是用HttpURLConnection发个请求,失败率是很高的。一般想要保证成功率的话,都会选择真实的浏览器去抓取。

以前常用的解决方案是selenium或phantomjs,但是它两的环境配置太麻烦了,对程序员极度不友好,自从谷歌推出Puppeteer后,puppeteer迅速流行起来,获得大家一致称赞。它是一个NodeJS库,但今天并不是要使用它来爬取某宝商品,而是使用Java语言写的Jvppeteer,Jvppeteer与Puppeteer是同样的实现原理。

思路:
  1. 使用多线程,一个线程负责一个页面的爬取,接下来的内内容会使用page代替页面
  2. 创建与线程池线程数相同的page队列,放在LinkedBlockingQueue队列里,每当有爬取任务时,就从队列里取出一个page,爬取任务完成时,将page放回队列的后面。这样做的原因是重复利用page,减少页面的创建频率,但是要注意的是一个页面不能利用太久或者次数太多,防止出现crash的情况
  3. 拦截图片和多媒体资源的加载,多媒体资源和图片的加载会极大影响页面的加载速度,从而影响爬虫效率,所以要拦截(可选)。
  4. 我们选择获取整个页面内容,然后解析得到商品信息
代码实现

1.启动

//指定启动路径,启动浏览器 String path = new String("F:\\java教程\\49期\\vuejs\\puppeteer\\.local-chromium\\win64-722234\\chrome-win\\chrome.exe".getBytes(), "UTF-8"); ArrayList<String> argList = new ArrayList<>(); LaunchOptions options = new Optionsbuilder().withArgs(argList).withHeadless(false).withExecutablePath(path).build(); argList.add("--no-sandbox"); argList.add("--disable-setuid-sandbox"); Browser browser = Puppeteer.launch(options);

2.page队列

//启动一个线程池多线程抓取 int threadCount = 5; ThreadPoolexecutor executor = new ThreadPoolExecutor(threadCount, threadCount, 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); CompletionService service = new ExecutorCompletionService(executor); //打开5个页面同时抓取,这些页面可以多次利用,这样减少创建网页带来的性能消耗 LinkedBlockingQueue<Page> pages = new LinkedBlockingQueue<>(); for (int i = 0; i < threadCount; i ) { Page page = browser.newPage(); //拦截请求,可选 // page.onrequest(request -> { // if ("image".equals(request.resourceType()) || "media".equals(request.resourceType())) { // //遇到多媒体或者图片资源请求,拒绝,加载页面加载 // request.abort(); // } else {//其他资源放行 // request.continueRequest(); // } // }); // page.setRequestInterception(true); pages.put(page);//往队列后面放,阻塞 }

3.定义爬取线程

static class CrawlerCallable implements Callable<Object> { private LinkedBlockingQueue<Page> pages; public CrawlerCallable(LinkedBlockingQueue<Page> pages) { this.pages = pages; } @Override public Object call() { Page page = null; try { page = pages.take(); PageNavigateOptions navigateOptions = new PageNavigateOptions(); navigateOptions.setWaitUntil(Arrays.asList("domcontentloaded")); System.out.println("gotothreadName:" Thread.currentThread().getName()); page.goTo("https://item.taobao.com/item.htm?id=541605195654", navigateOptions); String content = page.content(); //解析商品 return parseItem(content); } catch (Exception e) { e.printStackTrace(); } finally { if (page != null) { try { pages.put(page);//把已经抓取完的网页放回队列里 } catch (InterruptedException e) { e.printStackTrace(); } } } return null; } }

4.关闭线程池,获取结果

//结果集 List<future<Object>> futures = new ArrayList<>(); //抓取100次 long start = System.currentTimeMillis(); for (int i = 0; i < 100; i ) { Future<Object> future = service.submit(new CrawlerCallable(pages)); futures.add(future); } //关闭线程池 executor.shutdown(); //获取结果 int i = 0; for (Future<Object> result : futures) { Object item = result.get(); i ; System.out.println(i ":" Constant.OBJECTMAPPER.writeValueAsString(item)); } long end = System.currentTimeMillis(); System.out.println("时间:" (end - start));

在俺电脑测试,100个爬取任务只需要15s,速度还是非常的快。速度的快慢受到根据电配置以及带宽的影响,配置越好,速度越快。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved