初步定的方案用 python,因为IO读写方便,结合xpath,后来搭了环境,发现好多都忘记了,需要复习,所有最后决定用java,结合jsoup,htmlUtil等。
关于 jsoup ,可以看我的博客:Jsoup学习文档
捣鼓了一晚上,折腾到凌晨3、4点多,终于爬了下来。原本想一个页面下载小说的多个类型,后来发现做不到,一段代码并行跑的。
爬取小说的网站
设计到技术点:
需要模拟下载按钮的点击,还有之后弹出的确认框的按钮点击。这里的思路是调用两次按钮点击事件对应方法,第一次click返回page,获取按钮Element在调用一次返回的page直接输出为IO,
按钮的多次点击之间,页面会通过js动态生成Element。如果两次点击事件串行触发,可能需要的Element数据没有加载出来,获取不到第二次的按钮元素。报NullPointException。这个处理是让线程sleep了一秒。确保js加载的Element可以加载出来。
当前代码同一个页面不支持多次按钮点击下载,如果因为在一次下载完无法获取到当前页面了,所以不能并行操作,解决办法现在还没想到,小伙伴可以留言idea。
剩下的需要注意一些版本依赖问题。
默认的处理异常逻辑为,当前小说下载出现异常会直接跳过。
代码没有处理,需要优化的可以自行处理下
依赖
4.0.0 com.liruilon spider 1.0-SNAPSHOT org.apache.httpcomponents httpclient 4.5.7 org.jsoup jsoup 1.11.3 com.fasterxml.jackson.core jackson-databind 2.9.8 org.mozilla rhino 1.7.10 net.sourceforge.htmlunit htmlunit 2.33 junit junit 4.12 test org.slf4j slf4j-api 1.7.25 org.slf4j slf4j-log4j12 1.7.25 commons-beanutils commons-beanutils 1.9.4 commons-io commons-io 2.5 com.google.guava guava 18.0
import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.DomElement; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.google.common.collect.ImmutableMap; import com.google.common.io.Files; import org.apache.commons.io.FileUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.*; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import java.util.stream.Collectors; import static org.apache.commons.io.IOUtils.copyLarge; /** * @Description : * @Author: Liruilong * @Date: 2020/10/13 21:15 */ public class Test { static Logger logger = Logger.getLogger(Test.class.getCanonicalName()); static ExecutorService executorService = Executors.newFixedThreadPool(20); static final Map mapTextStyle = ImmutableMap.of( // "下載 updb 檔", "updb" // "下載 prc 檔", "prc" "下載直式 mobi 檔", "mobi" //"下載 epub 檔", "epub" ); /** * @param args * @return * @description * @author Liruilong * @date 2020年10月15日 03:10:12 **/ public static void main(String[] args) { String[] strings = new String[]{"http://www.haodoo.net/?M=hd&P=100", "http://www.haodoo.net/?M=hd&P=wisdom", "http://www.haodoo.net/?M=hd&P=history", "http://www.haodoo.net/?M=hd&P=martial", "http://www.haodoo.net/?M=hd&P=mystery", "http://www.haodoo.net/?M=hd&P=scifi", "http://www.haodoo.net/?M=hd&P=romance", "http://www.haodoo.net/?M=hd&P=fiction"}; for (int j = 0; j < strings.length; j++) { try { Document doc = null; doc = Jsoup.connect(strings[j]).get(); Elements s = doc.select("a[href]"); logger.info("爬取:" + strings[j] + "__________---------——————————————" + Thread.currentThread().getName()); List elements = s.stream().filter(a -> a.attr("abs:href").indexOf("book") != -1 && a.text().length() > 1) .collect(Collectors.toList()); executorService.execute(() -> { for (int i = 0; i < elements.size(); i++) { try { WebClient webclient = new WebClient(); logger.info("爬取:" + elements.get(i).text() + "__________---------——————————————" + Thread.currentThread().getName()); HtmlPage htmlpage = null; htmlpage = webclient.getPage(elements.get(i).attr("abs:href")); List domElements = htmlpage.getElementsByTagName("input").stream().filter(o -> mapTextStyle.containsKey(o.getAttribute("value"))).collect(Collectors.toList()); for (int i1 = 0; i1 < domElements.size(); i1++) { try { String textNameStyle = mapTextStyle.get(domElements.get(i1).getAttribute("value")); logger.info("爬取:" + elements.get(i).text() + "___" + textNameStyle + "_______---------——————————————" + Thread.currentThread().getName()); HtmlPage page = domElements.get(i1).click(); TimeUnit.SECONDS.sleep(1); DomElement button = page.getElementById("okButton"); if (Objects.isNull(button)) { TimeUnit.SECONDS.sleep(1); } final InputStream inputStream = button.click().getWebResponse().getContentAsStream(); saveFile(inputStream, elements.get(i).text(), textNameStyle); } catch (Exception e) { continue; } } webclient.close();//关掉 } catch (IOException e) { continue; } } }); } catch (IOException e) { e.printStackTrace(); } } } /** * @param io * @param s * @return 文件保存 * @description * @author Liruilong * @date 2020年10月15日 00:10:06 **/ public static void saveFile(InputStream io, String... s) { executorService.execute(() -> { logger.info("-----------------------------------------------------------------------导入开始:" + s[0] + "__________---------——————————————" + Thread.currentThread().getName()); try (OutputStream outputStream = new FileOutputStream(new File("G:\\codedemo\\src\\main\\" + s[0] .replaceAll("【", "").replaceAll("】", "") .replaceAll("《", "").replaceAll("》", "") + "." + s[1]));) { copyLarge(io, outputStream); outputStream.flush(); logger.info("-------------------------------------------------------------------------导入结束:" + s[0] + "__________---------——————————————" + Thread.currentThread().getName()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }); } }
Java 爬虫
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。