我們都知道很多數(shù)據(jù)都可以通過爬蟲進(jìn)行爬取霍比,如果我們爬取的是一個(gè)簡單的頁面策橘,那么很輕松就可以實(shí)現(xiàn)了元媚,如果要爬取動(dòng)態(tài)頁面甜无,那么怎么辦呢辩尊?
比如說我們要爬取東方財(cái)富網(wǎng)站上面的這些股票信息:
http://quote.eastmoney.com/center/list.html#10_0_0_u?sortType=C&sortRule=-1
但是我們查看源碼的時(shí)候卻看不到任何關(guān)于股票信息的數(shù)據(jù)划乖,可以看出這些股票數(shù)據(jù)是異步加載的蒂胞,果斷F12打開chrome開發(fā)者工具纸泄,在Network選項(xiàng)中查看基公,如果沒有的話可以F5刷新一下頁面就出來了幅慌。
然后點(diǎn)擊那個(gè)異步的api,會(huì)新打開一個(gè)頁面轰豆,出現(xiàn)以下的數(shù)據(jù):
var C1Cache={quotation:["0000011,上證指數(shù),3166.98,170854125568,13.89,0.44%,876|201|246|142,1380|270|360|204","3990012,深證成指,10130.12,215605108736,74.55,0.74%,876|201|246|142,1380|270|360|204"]}
本以為是一個(gè)json的數(shù)據(jù)欠痴,但是服務(wù)端傳來的是一個(gè)js變量迄靠,值類似一個(gè)json數(shù)據(jù),這應(yīng)該是為了開發(fā)的方便喇辽,但是我們要的是json的數(shù)據(jù)掌挚,所以需要過濾一下,split("=")然后取右邊的字符串就行了菩咨,但是需要注意下吠式,這個(gè)右邊的不是json數(shù)據(jù),注意json的key需要有雙引號(在java中和python中)抽米,或許在js下有沒有都可以吧特占,所以我們在java中還需要replace一下,這樣才是一個(gè)json字符串云茸,然后轉(zhuǎn)換成json對象是目,可以用jackson的 objectmapper,反正方法很多标捺。然后把這些數(shù)據(jù)持久化到數(shù)據(jù)庫就可以了懊纳,這樣我們就實(shí)現(xiàn)了一些動(dòng)態(tài)頁面的爬取。
但是這里需要注意的就是亡容,有些網(wǎng)站不允許你跨域去訪問嗤疯,即使你通過偽裝服務(wù)端還是有對策來防止你直接調(diào)用api,那么這個(gè)時(shí)候就需要用另一種方法闺兢,webmagic selenium茂缚,這個(gè)的原理就是,先運(yùn)行一個(gè)瀏覽器內(nèi)核去加載這個(gè)頁面屋谭,等到整個(gè)頁面加載完后再獲取html代碼脚囊,然后進(jìn)行處理。
比如說我們要爬取上交所的浦發(fā)銀行這支股票背后的公司信息桐磁,http://www.sse.com.cn/assortment/stock/list/info/company/index.shtml?COMPANY_CODE=600000
我們查看異步加載的api的時(shí)候凑术,發(fā)現(xiàn)不允許你直接的訪問這個(gè)api,所以只能用第二種方法了所意。
下面是項(xiàng)目的依賴:
compile 'us.codecraft:webmagic-core:0.5.3'
compile('us.codecraft:webmagic-extension:0.5.3')
compile 'org.seleniumhq.selenium:selenium-java:2.8.0'
compile group: 'us.codecraft', name: 'webmagic-selenium', version: '0.5.2'
源碼如下:
public class CompanyProcessor implements PageProcessor {
private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(3000)
.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36");
public void process(Page page) {
WebDriver driver = new ChromeDriver();
driver.get("http://www.sse.com.cn/assortment/stock/list/info/company/index.shtml?COMPANY_CODE=600000");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
WebElement webElement = driver.findElement(By.id("tableData_stockListCompany"));
// WebElement webElement = driver.findElement(By.xpath("http://div[@class='table-responsive sse_table_T05']"));
String str = webElement.getAttribute("outerHTML");
System.out.println(str);
Html html = new Html(str);
System.out.println(html.xpath("http://tbody/tr").all());
String companyCode = html.xpath("http://tbody/tr[1]/td/text()").get();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String dateString = html.xpath("http://tbody/tr[3]/td/text()").get().split("/")[0];
String stockCode = html.xpath("http://tbody/tr[2]/td/text()").get().split("/")[0];
String name = html.xpath("http://tbody/tr[5]/td/text()").get().split("/")[0];
String department = html.xpath("http://tbody/tr[14]/td/text()").get().split("/")[0];
System.out.println(companyCode);
System.out.println(stockCode);
System.out.println(name);
System.out.println(department);
driver.close();
}
public Site getSite() {
return site;
}
public static void main(String[] args) {
Spider.create(new CompanyProcessor())
.addUrl("http://www.sse.com.cn/assortment/stock/list/info/company/index.shtml?COMPANY_CODE=600000")
.thread(5)
.run();
}
}
這里面有一些webmagic的知識淮逊,如果不熟悉的可以看一下中文文檔,因?yàn)檫@個(gè)爬蟲框架是中國人寫的扶踊,所以中文文檔很詳細(xì)http://webmagic.io/docs/zh/
這里注意一下這行代碼:
WebDriver driver = new ChromeDriver();
如果要讓代碼運(yùn)行成功需要下載一個(gè)chromedriver泄鹏,如果你是windows可以去這個(gè)網(wǎng)址去下https://chromedriver.storage.googleapis.com/2.25/chromedriver_win32.zip,雖然是32位的但是64位也可以用秧耗,如果不行的話或者你是其他OS备籽,可以去官網(wǎng)下https://chromedriver.storage.googleapis.com/index.html?path=2.27/
這里為什么不直接推薦去官網(wǎng)下載最新的呢?因?yàn)槲抑坝眠^,最新的在我的兩個(gè)電腦上的windows系統(tǒng)都出現(xiàn)了問題〕碘現(xiàn)在完成后解壓放在C:\Windows\System32目錄下霉猛,或者設(shè)置一下環(huán)境變量都行。
然后就可以運(yùn)行了珠闰,之后的就是去提取一些數(shù)據(jù)或者url了惜浅,就像處理靜態(tài)頁面一樣了。