本文目錄一覽:
- 1、如何用Java寫一個爬蟲
- 2、有沒有比較好的Java並發爬蟲框架
- 3、有一個任務,說是用JAVA編程,編一個類似網絡爬蟲的東西,可以將網頁上的文字小說提取出來變為txt文檔。
- 4、java可以寫爬蟲嗎?
- 5、Java網絡爬蟲怎麼實現?
- 6、北大青鳥設計培訓:Java多線程爬蟲實現?
如何用Java寫一個爬蟲
最近剛好在學這個,對於一些第三方工具類或者庫,一定要看官方tutorial啊。
學會用chrome network 分析請求,或者fiddler抓包分析。
普通的網頁直接用httpclient封裝的API就可以獲取網頁HTML了,然後 JSoup、正則 提取內容。
若網站有反爬蟲機制的,會需要構造User-Agent 偽裝瀏覽器; 若有需要登錄的,會傳入cookie進去。
有些網頁可能是利用ajax技術的,可以嘗試PhantomJS拿到渲染後的HTML(然後步驟同上); 或者直接chrome network分析請求的URL以及傳參,然後直接拿到json。
關於圖片驗證碼的沒嘗試過,是不是要用到第三方ocr工具識別圖片驗證碼然後作為URL參數,希望做過的童鞋告知。
有沒有比較好的Java並發爬蟲框架
開發網絡爬蟲應該選擇Nutch、Crawler4j、WebMagic、scrapy、WebCollector還是其他的?這裡按照我的經驗隨便扯淡一下:上面說的爬蟲,基本可以分3類:1.分布式爬蟲:Nutch
2.JAVA單機爬蟲:Crawler4j、WebMagic、WebCollector
3. 非JAVA單機爬蟲:scrapy
第一類:分布式爬蟲
爬蟲使用分布式,主要是解決兩個問題:
1)海量URL管理
2)網速
有一個任務,說是用JAVA編程,編一個類似網絡爬蟲的東西,可以將網頁上的文字小說提取出來變為txt文檔。
如果單線程來實現,就是一個主程序去爬,不斷遍歷。很簡單的。
如果多線程,就主程序控制多線程去進行遍歷。最好用一個線程池來進行管理,否則會隨着遍歷系統資源消耗過大的。
java可以寫爬蟲嗎?
codeblocks能不能寫我不知道,但不僅僅只有java可以寫爬蟲,還有像python等的語言也可以寫
Java網絡爬蟲怎麼實現?
網絡爬蟲是一個自動提取網頁的程序,它為搜索引擎從萬維網上下載網頁,是搜索引擎的重要組成。
傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定停止條件。對於垂直搜索來說,聚焦爬蟲,即有針對性地爬取特定主題網頁的爬蟲,更為適合。
以下是一個使用java實現的簡單爬蟲核心代碼:
public void crawl() throws Throwable {
while (continueCrawling()) {
CrawlerUrl url = getNextUrl(); //獲取待爬取隊列中的下一個URL
if (url != null) {
printCrawlInfo();
String content = getContent(url); //獲取URL的文本信息
//聚焦爬蟲只爬取與主題內容相關的網頁,這裡採用正則匹配簡單處理
if (isContentRelevant(content, this.regexpSearchPattern)) {
saveContent(url, content); //保存網頁至本地
//獲取網頁內容中的鏈接,並放入待爬取隊列中
Collection urlStrings = extractUrls(content, url);
addUrlsToUrlQueue(url, urlStrings);
} else {
System.out.println(url + ” is not relevant ignoring …”);
}
//延時防止被對方屏蔽
Thread.sleep(this.delayBetweenUrls);
}
}
closeOutputStream();
}
private CrawlerUrl getNextUrl() throws Throwable {
CrawlerUrl nextUrl = null;
while ((nextUrl == null) (!urlQueue.isEmpty())) {
CrawlerUrl crawlerUrl = this.urlQueue.remove();
//doWeHavePermissionToVisit:是否有權限訪問該URL,友好的爬蟲會根據網站提供的”Robot.txt”中配置的規則進行爬取
//isUrlAlreadyVisited:URL是否訪問過,大型的搜索引擎往往採用BloomFilter進行排重,這裡簡單使用HashMap
//isDepthAcceptable:是否達到指定的深度上限。爬蟲一般採取廣度優先的方式。一些網站會構建爬蟲陷阱(自動生成一些無效鏈接使爬蟲陷入死循環),採用深度限制加以避免
if (doWeHavePermissionToVisit(crawlerUrl)
(!isUrlAlreadyVisited(crawlerUrl))
isDepthAcceptable(crawlerUrl)) {
nextUrl = crawlerUrl;
// System.out.println(“Next url to be visited is ” + nextUrl);
}
}
return nextUrl;
}
private String getContent(CrawlerUrl url) throws Throwable {
//HttpClient4.1的調用與之前的方式不同
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url.getUrlString());
StringBuffer strBuf = new StringBuffer();
HttpResponse response = client.execute(httpGet);
if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader reader = new BufferedReader(
new InputStreamReader(entity.getContent(), “UTF-8”));
String line = null;
if (entity.getContentLength() 0) {
strBuf = new StringBuffer((int) entity.getContentLength());
while ((line = reader.readLine()) != null) {
strBuf.append(line);
}
}
}
if (entity != null) {
nsumeContent();
}
}
//將url標記為已訪問
markUrlAsVisited(url);
return strBuf.toString();
}
public static boolean isContentRelevant(String content,
Pattern regexpPattern) {
boolean retValue = false;
if (content != null) {
//是否符合正則表達式的條件
Matcher m = regexpPattern.matcher(content.toLowerCase());
retValue = m.find();
}
return retValue;
}
public List extractUrls(String text, CrawlerUrl crawlerUrl) {
Map urlMap = new HashMap();
extractHttpUrls(urlMap, text);
extractRelativeUrls(urlMap, text, crawlerUrl);
return new ArrayList(urlMap.keySet());
}
private void extractHttpUrls(Map urlMap, String text) {
Matcher m = (text);
while (m.find()) {
String url = m.group();
String[] terms = url.split(“a href=\””);
for (String term : terms) {
// System.out.println(“Term = ” + term);
if (term.startsWith(“http”)) {
int index = term.indexOf(“\””);
if (index 0) {
term = term.substring(0, index);
}
urlMap.put(term, term);
System.out.println(“Hyperlink: ” + term);
}
}
}
}
private void extractRelativeUrls(Map urlMap, String text,
CrawlerUrl crawlerUrl) {
Matcher m = relativeRegexp.matcher(text);
URL textURL = crawlerUrl.getURL();
String host = textURL.getHost();
while (m.find()) {
String url = m.group();
String[] terms = url.split(“a href=\””);
for (String term : terms) {
if (term.startsWith(“/”)) {
int index = term.indexOf(“\””);
if (index 0) {
term = term.substring(0, index);
}
String s = //” + host + term;
urlMap.put(s, s);
System.out.println(“Relative url: ” + s);
}
}
}
}
public static void main(String[] args) {
try {
String url = “”;
Queue urlQueue = new LinkedList();
String regexp = “java”;
urlQueue.add(new CrawlerUrl(url, 0));
NaiveCrawler crawler = new NaiveCrawler(urlQueue, 100, 5, 1000L,
regexp);
// boolean allowCrawl = crawler.areWeAllowedToVisit(url);
// System.out.println(“Allowed to crawl: ” + url + ” ” +
// allowCrawl);
crawler.crawl();
} catch (Throwable t) {
System.out.println(t.toString());
t.printStackTrace();
}
}
北大青鳥設計培訓:Java多線程爬蟲實現?
一、需求 1.定時抓取固定網站新聞標題、內容、發表時間和來源。
2.程序需要支持分布式、多線程 二、設計 1.網站是固定,但是未來也可能添加新的網站去抓取,每個網站內容節點設計都不一樣,這樣就需要支持動態可配置來新增網站以方便未來的擴展,這樣就需要每次都需要開發介入。
2.網站html節點的結構可能發生變化,所以也要支持提取節點可配置。
3.怎樣支持分布式?暫時最簡單的想法就是:多機器部署程序,還有新搞一台或者部署程序其中一台製作一個定時任務,定時開啟每台機器應該抓取哪個網站,暫時不能支持同一個網站同時可以支持被多台機器同時抓取,這樣會比較麻煩,要用到分布式隊列。
所以暫時一個網站同時只會被單台機器抓取。
4.多線程,怎樣多線程?多線程抓取我這邊有兩個實現: (1)一個線程抓取一個網站,維護一個自己的url隊列做廣度抓取,同時抓取多個網站。
如圖: (2)多個線程同時抓取不同的網站。
如圖: 以上兩張辦法其實各有優點,也給有缺點,看我們怎麼取捨了。
方法1:每個線程創建一個自己的隊列,圖中的queue可以不用concurrentQueue,優點:不涉及到控制並發,每個網站一個線程抓取一個網站,抓取完畢即自動回收銷毀線程。
控制方便。
缺點:線程數不可以擴展,例如當只有3個網站,你最多只能開3個線程來抓取,不能開更多,有一定的局限性。
方法2:N個線程同時抓取N個網站,線程數和網站數目不掛鈎,優點:線程數可以調整並且和和抓取網站數量無關。
3個網站我們可以開4個5個或者10個這個可以根據您的硬件資源進行調整。
缺點:需要控制並發,並且要控制什麼時候銷毀線程(thread1空閑,並且queue為空不代表任務可以結束,可能thread2結果還沒返回),當被抓取的網站響應較慢時,會拖慢整個爬蟲進度。
三、實現 抓取方式最終還是選擇了方法二,因為線程數可配置! 使用技術: jfinal用了之後才發現這東西不適合,但是由於項目進度問題,還是使用了。
maven項目管理 jettyserver mysql eclipse開發 項目需要重點攻破的難點: (1)合理的控制N個線程正常的抓取網站,並且當所有線程工作都完成了並且需要抓取的隊列為空時,N個線程同時退出銷毀。
(2)不同網站設計節點不一樣,需要通過配置解決各個網站需要抓取的URL和抓取節點內容在html節點的位置。
(3)個性化內容處理,由於html結構設計問題,北大青鳥認為抓取的內容可能有些多餘的html標籤,或者多餘的內容該怎麼處理。
原創文章,作者:PYKZ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/139854.html