Java使用selenium爬取加密网页
一般的网站可直接通过HttpClient进行网页爬取,但是如果一些网站用了js加密模板引擎的话,可能就爬取不到了
比如豆瓣的图书搜索页 : https://book.douban.com/subject_search?search_text=9787534293467
所以需要用到爬取数据的保底神器selenium,这个是完全模拟人的操作 , 所以只要网页看得到 ,它就爬的到
不过用起来也很麻烦,需要装驱动和浏览器,本文以Chrome浏览器为例。
(Windows的操作比较简单 , 自行根据本文研究 , 本文主要讲Linux下 , 测试环境为 CentOS7)
1.下载驱动
https://chromedriver.chromium.org/
直接下载就行
下载好之后 , 把解压后的文件 , 放到 /usr/bin/ 目录下面即可
2.Linux下安装谷歌
本文环境为 CentOS7.1
#直接安装 ,或者把脚本下载下来之后再安装 , 都行 curl https://intoli.com/install-google-chrome.sh | bash
安装完成之后的校验
[root@localhost ~]# google-chrome --version Google Chrome 97.0.4692.99
3.适用selenium爬取网页
/** * 使用浏览器模式爬取网页 , 需要本机安装Chrome和Chrome支持插件 * * @param baseUrl 需要爬取的网页 * @param waitDom 防止页面加载不全 , 而校验页面中的元素是否存在 , 语法参考jQuery , 比如 div[id='root'] * @param waitSecond 防止页面加载不全的最大等待时间 * @param chromeDriverDir ChromeDriver 执行文件指定位置 , 如果配置环境变量 , 可不设 * @param chromeBinaryDir Chrome可执行文件路径 , 如果是默认路径 , 可不设 * @author kreo * @date 2022/1/25 13:19 */ public static String htmlGet(String baseUrl, String waitDom, Long waitSecond, String chromeDriverDir, String chromeBinaryDir) { // 搜索的地址 // String baseUrl = SEARCH + isbn + "&cat=1001"; // 指定ChromeDriver的地址 if (IStr.isNotBlank(chromeDriverDir)) { log.debug("设置ChromeDriverDir >>> " + chromeDriverDir); System.setProperty("webdriver.chrome.driver", chromeDriverDir); } // 配置Chrome参数 ChromeOptions options = new ChromeOptions(); // 无浏览器模式 options.addArguments("--headless"); options.addArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"); options.addArguments("--referer=" + baseUrl); // 配置Chrome的执行地址 if (IStr.isNotBlank(chromeBinaryDir)) { log.debug("设置ChromeBinaryDir >>> " + chromeBinaryDir); options.setBinary(chromeBinaryDir); } WebDriver driver = null; try { driver = new ChromeDriver(options); // 载入网页 log.info("爬取网页 >>> " + baseUrl); driver.get(baseUrl); // 模拟设置Cookie Cookie cookie = new Cookie("bid", "*"); driver.manage().addCookie(cookie); // 防止页面加载不完全 , 默认最长等待10秒 if (IStr.isNotBlank(waitDom)) { By by = By.cssSelector("div[id='root']"); waitForLoad(driver, by, IType.getLong(waitSecond, 15L)); } return driver.getPageSource(); } catch (Exception e) { log.error(">>>> 读取失败 >>> ", e); return null; } finally { if (driver != null) { driver.quit(); } } } /** * 等待元素加载 * * @param driver * @param by */ public static void waitForLoad(final WebDriver driver, final By by, final long waitSecond) { new WebDriverWait(driver, Duration.ofSeconds(waitSecond)).until( (ExpectedCondition<Boolean>) d -> { WebElement element = driver.findElement(by); if (element != null) { return true; } return false; }); }
测试 >>>>>>> :
/** 搜索地址 */ private static final String SEARCH = "https://book.douban.com/subject_search?search_text="; public static void main(String[] args) throws IOException { // 本机Windows下测试 // 如果是Linux下 , chromeDriverDir/chromeBinaryDir 都可设为null String pageSource = htmlGet( SEARCH + "9787534293467" + "&cat=1001", "div[id='root']", 10L, "D:/DevTools/ChromeDriver/chromedriver_win32/chromedriver.exe", "C:/Program Files/Google/Chrome/Application/chrome.exe" ); System.out.println(pageSource); }
或者用jsoup >>>
List<ImmutableMap<String, Object>> bookInfos = null; Document baseDoc = Jsoup.parse(pageSource); Elements itemBookEles = baseDoc.select("a[class=title-text]"); if (itemBookEles != null && itemBookEles.size() > 0) { bookInfos = Lists.newArrayList(); for (Element itemBookEle : itemBookEles) { String href = itemBookEle.attr("href"); bookInfos.add( ImmutableMap.<String, Object>builder() .put("title", itemBookEle.text()) .put("href", href) .build() ); } }