背景说明:
对于很多传统的服务端渲染的网页来说,抓取还是比较容易的;
但是目前很多前端渲染的页面就要依靠浏览器驱动调起浏览器,打开页面,再获取到页面内容进行分析;
Java网络爬虫工具选择:
1,Webmagic,该工具有丰富的例子和文档,传送门:http://webmagic.io/
2,selenium+jsoup+chrome-driver(前端渲染,后端渲染都适用,今天我们主要介绍这种方式)
前提准备:
1,下载chrome浏览器,并安装;(如果服务部署在linux服务器,则需要下载linux版本);
2,下载chrome-driver,地址:http://npm.taobao.org/mirrors/chromedriver/
注意:chromedriver的版本一定要和安装的chrome版本一致;(我下载的小版本号不一致,但也能调起浏览器);
3,maven 依赖:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId><version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId><version>3.141.59</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.5</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
上代码:
@Test
public void jdTest() {
//设置浏览器驱动位置
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
//搜索关键字
String keywords = "笔记本";
String url = "https://www.jd.com";
logger.info("url:{}",url);
//浏览器相关设置
ChromeOptions options = new ChromeOptions();
//无界面模式,不会弹出浏览器
options.setHeadless(true);
//代理设置,但是目测并没有什么用
// String proxyIp = "182.87.129.127:9999";
// Proxy proxy = new Proxy();
// proxy.setHttpProxy(proxyIp);
// options.setProxy(proxy);
Map<String, Object> prefs = new HashMap<String, Object>();//浏览器配置
prefs.put("profile.default_content_settings.popups", 0);//禁止弹窗
// prefs.put("download.default_directory", "/data/download");//下载路径
// prefs.put("profile.managed_default_content_settings.images", 2);//禁止图片加载
prefs.put("profile.default_content_setting_values.notifications", 2);//禁止发送通知
boolean isMobile = false;
if(isMobile) { //手机浏览器模式
// String android = "User-Agent='MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'";
String iphone ="User-Agent=Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4";
prefs.put("profile.general_useragent_override", iphone);//设置UA
HashMap<String, Object> mobileEmulation = new HashMap<String, Object>();
mobileEmulation.put("deviceName","iPhone X");
options.setExperimentalOption("mobileEmulation", mobileEmulation);//移动端设置
}
options.setExperimentalOption("prefs", prefs);
options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});//不提示“Chrome正受到自动测试软件控制”
options.addArguments("--allow-running-insecure-content");//消除安全校验
options.setExperimentalOption("useAutomationExtension", false);
options.addArguments("--disable-blink-features");
options.addArguments("--disable-blink-features=AutomationControlled");
options.addArguments("no-sandbox");
WebDriver driver = new ChromeDriver(options);
driver.get(url);
//等待浏览器渲染页面再找到相关的元素
WebDriverWait wait = new WebDriverWait(driver,10,2);
WebElement searchInput = wait.until(new ExpectedCondition<WebElement>(){
@Override
public WebElement apply(WebDriver text) {
return text.findElement(By.id("key"));
}
});
//把关键字填入搜索框
searchInput.sendKeys(keywords);
//模拟点击搜索按钮
driver.findElement(By.xpath("//div[@class='form']/button")).click();
//模拟浏览器竖向滚动条向下滚动
for(int i=1;i<=3;i++) {
int s = i*1000;
((JavascriptExecutor)driver).executeScript("scroll(0,"+s+");");
ThreadUtil.safeSleep(1*1000);
}
//根据xpath中的条件找到符合条件的所有元素
List<WebElement> weList = wait.until(new ExpectedCondition<List<WebElement>>(){
@Override
public List<WebElement> apply(WebDriver text) {
return text.findElements(By.xpath("//li[@class='gl-item']"));
}
});
//正常解析元素
if(CollUtil.isNotEmpty(weList)) {
for(WebElement item : weList) {
logger.info("sku:{}",item.getAttribute("data-sku"));
logger.info("title:{}",item.findElement(By.xpath("//div[@class='p-img']/a")).getAttribute("title"));
logger.info("price:{}",item.findElement(By.xpath("//div[@class='p-price']/strong/i")).getText());
logger.info("url:{}",item.findElement(By.xpath("//div[@class='p-img']/a")).getAttribute("href"));
logger.info("-----------------------------------------------------------------------");
}
}
//使用Jsoup解析元素
String docStr = driver.getPageSource();
Document doc = Jsoup.parse(docStr);
Elements elements = doc.select("li.gl-item");
//获取每个元素中的相关数据
for(Element element : elements) {
logger.info("sku:{}",element.attr("data-sku"));
Element ele = element.selectFirst("div.p-img").selectFirst("a");
logger.info("title:{}",ele.attr("title"));
logger.info("price:{}",element.selectFirst("div.p-price").selectFirst("i").text());
logger.info("url:{}",StrUtil.replace(ele.attr("href"), "//", "https://"));
logger.info("----------------------------------------------------------------------");
}
//退出浏览器
driver.quit();
}
问题:
对于一些电商网站(例如:淘宝网)对浏览器驱动也进行了识别;当使用驱动调起浏览器,进行数据爬取时,直接被禁止搜索,登录等操作!原因是chromedriver在调起
chrome的时候设置了一个变量;淘宝网识别了这个变量,目前我用的版本试遍了各种方法,都没法更改变量,绕过淘宝的识别