本文已獨家授權給腳本之家(jb51net)、新華前后端開發公眾號發布
做技術我們最重要的是【做】。但是今天我們來講片【玩】。這句話可能不太好理解。直接開門見山吧。對於外行朋友一談到IT他們對我們的定位就是黑客。其實我們和黑客一點關系都沒有。今天的技術是【爬蟲】 。 為什么說爬蟲和黑客有點關聯呢。因為爬蟲可以將人為行為進行機器化。就是實現編寫好代碼讓機器代替我們人類重復的操作意見事情。
對於爬蟲了我們這里不做基礎的講解了。在平時的開發中我們偶爾會用到爬蟲。比如說我們系統需要添加天氣情況。但是我們有沒有氣象站給我提供數據。這時候我們最顯示的做法就是調用網絡上免費的天氣接口API 。 這個時候我們Java就會通過爬蟲模擬除一個瀏覽器請求去訪問這個天氣接口的API。 然后在通過爬蟲獲取這個API返回的數據。從而進行解析。
對於這些免費的API我們通過爬蟲(HttpClient)就可以輕松的訪問了。但是想優酷、愛奇藝、掘金這些等級網站他們會有發爬蟲策略。最常見的就是利用爬蟲進行刷票的行為。他們針對這些刷票做了一些措施。具體措施就不說了(不知道)。更有甚者他們對他們的頁面進行加密。讓你無法分析他們的html.或者加大你分析的成本。以上就是之前我們用爬蟲爬取數據遇到的一些問題。下面簡單梳理下我們遇到爬蟲的問題
- 網絡反爬蟲
- 網絡人為審核
- 登錄驗證碼
- 需要了解網站(需要有代碼經驗進行html分析)
selenium
今天我們帶了一個好東西。它轉變了我們傳統爬蟲的思路。傳統的爬蟲我們會去按照開發者的思路去處理邏輯。但是selenium他不需要關注開發者邏輯。只需要我們關注自己的需求。什么意思呢?就是說selenium他就是在模擬用戶的行為,你告訴selenium我需要點擊頁面的某個按鈕了,他就去點擊了。你告訴他我需要在某個輸入框中輸入內容了。他就去給你輸入內容。有了它,你再也不用管輸入內容之后提交登錄真正請求了。這樣的好處是降低了爬蟲的學習成本。對於不懂技術的人也可以很快上手了。
環境准備
這個是干嘛的呢?這里先透露下selenium使用的是瀏覽器的內核操作頁面的。所以這里需要現在內核。下載內核前提是電腦上有瀏覽器。筆者這里電腦上瀏覽器是Google 1.73版本 。 所以下載內核就得是對應的版本,否則會報錯的。在notes.txt文件中會列出每個對應的瀏覽器的版本的。
代碼環境
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
開始爬蟲
想想我們平時瀏覽網頁的時候是需要先打開瀏覽器,這里也是一樣。
【我們需要打開瀏覽器】(我的內核放在/root/Downloads/chromedriver)
ChromeOptions chromeOptions = new ChromeOptions();
File chromeDriverPath = new File("/root/Downloads/chromedriver");
System.setProperty("webdriver.chrome.driver", chromeDriverPath.getAbsolutePath());
chromeOptions.addArguments("--headless");
chromeOptions.addArguments("--disable-gpu");
//ubuntu瀏覽器中需要添加
chromeOptions.addArguments("--no-sandbox");
webDriver = new ChromeDriver(chromeOptions);
headless : 表示隱式打開瀏覽器,因為做爬蟲就不需要顯示界面了。
no-sandbox : 這個是因為我的Ubuntu安裝的google需要這個參數,所以這里也需要加上
disable-gpu : 同上
【輸入鏈接地址】(https://juejin.im/)
webDriver.get("https://juejin.im/");
,這樣內核就獲取到了我們在瀏覽器中看到的效果。那么我們這么獲取我們需要的頁面數據呢。
findElement
通過這個方法我們可以獲取到我們想要的任何數據。換句話說通過這個方法這個頁面在你面前一覽無余。包括他的衍生頁面
有的讀者有疑問了。我該怎么讓他獲取我想要的東西呢。
我們可以看出來這個方法里只有一個參數,By對象。這個By對象里提供了如下方法
- id
- linkText
- partialLinkText
- name
- tagName
- xpath
- className
- cssSelector
上面這些方法就是我們定位元素的方法。什么意思呢,我們前段朋友們經常通過jquery操作html的dom對象,在By對象里cssSelector就是和jquery同樣的操作方法。好多都是和jquery類似的。這里不懂技術的人會說這里技術點很難。其實不難。 我們不懂代碼的怎么辦呢。我們在瀏覽器瀏覽頁面 。 比如下圖中我想獲取我的博客名稱(框架原理那點事--不就反射嘛。)
我們鼠標放在【框架原理那點事--不就反射嘛】上右鍵選擇【檢查】。會自動跳轉到對應的代碼的
后面三種對應By里面的制定方法。這里就不說了。
操作js
WebElement webElement = webDriver.findElement(By.cssSelector("xxxxxx"));
JavascriptExecutor js = (JavascriptExecutor) webDriver;
js.executeScript("arguments[0].click();",digg);
上面的webElement是頁面中一個按鈕。我們可以直接webElement.click()讓按鈕點擊或者webElement.submit()提交Form表單。但是有的時候會不起作用。這個時候用上面的代碼可以進行點擊。
截圖
File source = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
try {
Files.copy(source.toPath(), new FileOutputStream(new File("/root/Downloads/test/1.png")));
} catch (IOException e) {
e.printStackTrace();
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
我們內核操作因為正常不開瀏覽器界面,但是我們調試的時候又想知道結果,可以打印除當前窗口的圖片。就是上述的代碼
切換窗口
Set<String> windowHandles = webDriver.getWindowHandles();
for (String windowHandle : windowHandles) {
if (!windowHandle.equals(webDriver.getWindowHandle())) {
//webDriver.switchTo().window(windowHandle);
}
}
在當前窗口切換訪問地址
webDriver.navigate().to("https://juejin.im/post/5d76f6585188254cc27b2af4");
webDriver.get("https://juejin.im/post/5d76f6585188254cc27b2af4");
管理cookie
webDriver.get("https://juejin.im/timeline");
webDriver.manage().addCookie(cookie);
webDriver.get("https://juejin.im/post/5d76f6585188254cc27b2af4");
這里值得注意的是,在添加cookie之前我們需要先訪問主頁,告訴內核我們后面添加的cookie是給那個Host下添加的。這樣我們添加的cookie才會有效。如上我們在juejin.im這個Host下都添加了Cookie。
個人網站(https://zxhtom.oschina.io)
個人微信(zxh870775401)
微信公眾號 : 新華前后端開發