Java网络爬虫开发

原创
2021/10/12 17:43
阅读数 1.4K

背景说明:

    对于很多传统的服务端渲染的网页来说,抓取还是比较容易的;

但是目前很多前端渲染的页面就要依靠浏览器驱动调起浏览器,打开页面,再获取到页面内容进行分析;

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的时候设置了一个变量;淘宝网识别了这个变量,目前我用的版本试遍了各种方法,都没法更改变量,绕过淘宝的识别

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部