本文目錄一覽:
- 1、java爬蟲一段話里的部分字元亂碼解決
- 2、java 實現網路爬蟲用哪個爬蟲框架比較好
- 3、爬蟲為什麼不用java要用 Python
- 4、Java源碼 實現網路爬蟲?
- 5、Java爬蟲方向怎麼樣?
- 6、Java網路爬蟲怎麼實現?
java爬蟲一段話里的部分字元亂碼解決
1. 網路爬蟲亂碼的原因。
源網頁的編碼與抓取後的編碼轉換不一致。如果源網頁是gbk編碼的位元組流,程序在我們抓取後直接用utf-8編碼輸出到存儲文件,這必然會造成亂碼,即當源網頁編碼與程序抓取後直接處理編碼一致時,就不會出現亂碼,然後統一字元編碼後也就不會出現亂碼。注意區分源網路代碼A,程序B直接使用的代碼,統一轉換字元的代碼C。
2. 是網頁的伺服器端代碼。
B.捕獲的數據原本是位元組數組,由A編碼,只有B=A才能保證不會出現亂碼;否則,當字符集不兼容時,就會出現亂碼字元。這一步常用於測試。
c、統一轉碼是指在獲得網頁的原始編碼A後進行統一編碼,主要是將每個網頁的數據統一成一種編碼,往往首選字符集較大的utf-8。
每個網頁都有自己的代碼,比如gbk,utf-8,iso8859-1,日本jp系統代碼,西歐,俄語等等。爬行時,所有類型的代碼都將被擴展。有的爬蟲只是簡單的識別網頁,然後統一編碼,有的則直接按照utf-8統一處理,不需要判斷源網頁,顯然會造成亂碼。
3. 亂碼的解決方案。
根據原因找到解決辦法很簡單。
1) 確定源網頁的代碼a。
代碼a通常位於網頁的三個位置,即httpheader的內容、網頁的元字符集和網頁標題中的文檔定義。獲取源網頁代碼時,依次判斷這三部分數據,從頭到尾優先順序相同。
理論上這是對的,但是國內有些網站不符合標準。比如寫出來的gbk其實是utf-8,有的寫出來是utf-8,其實是gbk。當然這是幾個網站,但是確實存在。因此,在確定網頁編碼時,應該對這種特殊情況給予特殊處理,如中文檢查、默認編碼等策略。
在另一種情況下,如果以上三種都沒有編碼信息,一般使用第三方的網頁編碼智能識別工具,如cpdetector。原理是通過統計位元組數組的特性來計算實際編碼,有一定的準確率,但是我發現在實踐中準確率還是很有限的。
但是綜合以上三種編碼確認方法後,中文亂碼的問題幾乎可以完全解決。在我的基於nutch1.6的網路爬蟲系統中,經過統計,編碼準確率可以達到99.99%,這也證明了上述方法和策略的可行性。
2) 程序通過代碼b還原源網頁數據。
顯然,這裡的B應該等於a,在java中,如果源網頁的位元組數組是source_byte_array,就會轉換成stringstr=newstring(source_byte_array,B)。即這些位元組數組對應的字元被正確編碼顯示在內存中,此時列印結果正常。此步驟通常用於調試或控制台輸出測試。
3) 統一轉碼。
網路爬蟲系統中有很多數據源。如果無法使用數據,它將被轉換為其原始數據,如果這樣做是浪費的。所以一般爬蟲系統要對抓取的結果進行統一編碼,做到一致,使用方便。此時,在(2)的基礎上,可以進行統一的編碼轉換,在java中的實現如下。
源網頁的位元組數組是source_byte_array。
轉換為普通字元串:stringnormal_source_str=newstring(source_byte_array,c)。這時候可以直接用javaapi存儲,但是字元串往往不直接寫。因為一般爬蟲存儲是將多個源網頁存儲在一個文件中,所以要記錄位元組偏移量,所以下一步。 再將得到的str轉換為統一的編碼C格式的位元組數組,則byte[] new_byte_array=normal_source_str.getBytes(C)即可,此時即可用java io api將數組寫入文件,並記錄相應的位元組數組偏移量等,待真正使用時,直接io讀取即可。
爬蟲過程不僅會存在亂碼問題,還會存在網站爬取涉及法律、IP受限,爬取行為受限等等問題,這個時候就需要不斷去解決這些問題。
java 實現網路爬蟲用哪個爬蟲框架比較好
有些人問,開發網路爬蟲應該選擇Nutch、Crawler4j、WebMagic、scrapy、WebCollector還是其他的?這裡按照我的經驗隨便扯淡一下:
上面說的爬蟲,基本可以分3類:
1.分散式爬蟲:Nutch
2.JAVA單機爬蟲:Crawler4j、WebMagic、WebCollector
3. 非JAVA單機爬蟲:scrapy
第一類:分散式爬蟲
爬蟲使用分散式,主要是解決兩個問題:
1)海量URL管理
2)網速
現在比較流行的分散式爬蟲,是Apache的Nutch。但是對於大多數用戶來說,Nutch是這幾類爬蟲里,最不好的選擇,理由如下:
1)Nutch是為搜索引擎設計的爬蟲,大多數用戶是需要一個做精準數據爬取(精抽取)的爬蟲。Nutch運行的一套流程里,有三分之二是為了搜索引擎而設計的。對精抽取沒有太大的意義。也就是說,用Nutch做數據抽取,會浪費很多的時間在不必要的計算上。而且如果你試圖通過對Nutch進行二次開發,來使得它適用於精抽取的業務,基本上就要破壞Nutch的框架,把Nutch改的面目全非,有修改Nutch的能力,真的不如自己重新寫一個分散式爬蟲框架了。
2)Nutch依賴hadoop運行,hadoop本身會消耗很多的時間。如果集群機器數量較少,爬取速度反而不如單機爬蟲快。
3)Nutch雖然有一套插件機制,而且作為亮點宣傳。可以看到一些開源的Nutch插件,提供精抽取的功能。但是開發過Nutch插件的人都知道,Nutch的插件系統有多蹩腳。利用反射的機制來載入和調用插件,使得程序的編寫和調試都變得異常困難,更別說在上面開發一套複雜的精抽取系統了。而且Nutch並沒有為精抽取提供相應的插件掛載點。Nutch的插件有隻有五六個掛載點,而這五六個掛載點都是為了搜索引擎服務的,並沒有為精抽取提供掛載點。大多數Nutch的精抽取插件,都是掛載在「頁面解析」(parser)這個掛載點的,這個掛載點其實是為了解析鏈接(為後續爬取提供URL),以及為搜索引擎提供一些易抽取的網頁信息(網頁的meta信息、text文本)。
4)用Nutch進行爬蟲的二次開發,爬蟲的編寫和調試所需的時間,往往是單機爬蟲所需的十倍時間不止。了解Nutch源碼的學習成本很高,何況是要讓一個團隊的人都讀懂Nutch源碼。調試過程中會出現除程序本身之外的各種問題(hadoop的問題、hbase的問題)。
5)很多人說Nutch2有gora,可以持久化數據到avro文件、hbase、mysql等。很多人其實理解錯了,這裡說的持久化數據,是指將URL信息(URL管理所需要的數據)存放到avro、hbase、mysql。並不是你要抽取的結構化數據。其實對大多數人來說,URL信息存在哪裡無所謂。
6)Nutch2的版本目前並不適合開發。官方現在穩定的Nutch版本是nutch2.2.1,但是這個版本綁定了gora-0.3。如果想用hbase配合nutch(大多數人用nutch2就是為了用hbase),只能使用0.90版本左右的hbase,相應的就要將hadoop版本降到hadoop 0.2左右。而且nutch2的官方教程比較有誤導作用,Nutch2的教程有兩個,分別是Nutch1.x和Nutch2.x,這個Nutch2.x上寫的是可以支持到hbase 0.94。但是實際上,這個Nutch2.x的意思是Nutch2.3之前、Nutch2.2.1之後的一個版本,這個版本在官方的SVN中不斷更新。而且非常不穩定(一直在修改)。
所以,如果你不是要做搜索引擎,盡量不要選擇Nutch作為爬蟲。有些團隊就喜歡跟風,非要選擇Nutch來開發精抽取的爬蟲,其實是沖著Nutch的名氣(Nutch作者是Doug Cutting),當然最後的結果往往是項目延期完成。
如果你是要做搜索引擎,Nutch1.x是一個非常好的選擇。Nutch1.x和solr或者es配合,就可以構成一套非常強大的搜索引擎了。如果非要用Nutch2的話,建議等到Nutch2.3發布再看。目前的Nutch2是一個非常不穩定的版本。
爬蟲為什麼不用java要用 Python
這個問題蠻有意思的。
簡單的發表一些個人 淺見哈。
1、Java實現網路爬蟲的代碼要比Python多很多,而且實現相對複雜一些。
2、Java對於爬蟲的相關庫也有,但是沒有Python那麼多。
不過就爬蟲的效果來看,Java和Python都能做到,只不過工程量不同,實現的方式也有所差異。
更多的優劣期待大佬們不吝賜教。
推薦教程: 《Python教程》以上就是小編分享的關於爬蟲為什麼不用java要用 Python的詳細內容希望對大家有所幫助,更多有關python教程請關注環球青藤其它相關文章!
Java源碼 實現網路爬蟲?
//Java爬蟲demo
import java.io.File;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DownMM {
public static void main(String[] args) throws Exception {
//out為輸出的路徑,注意要以\\結尾
String out = “D:\\JSP\\pic\\java\\”;
try{
File f = new File(out);
if(! f.exists()) {
f.mkdirs();
}
}catch(Exception e){
System.out.println(“no”);
}
String url = “-“;
Pattern reg = Pattern.compile(“img src=\”(.*?)\””);
for(int j=0, i=1; i=10; i++){
URL uu = new URL(url+i);
URLConnection conn = uu.openConnection();
conn.setRequestProperty(“User-Agent”, “Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko”);
Scanner sc = new Scanner(conn.getInputStream());
Matcher m = reg.matcher(sc.useDelimiter(“\\A”).next());
while(m.find()){
Files.copy(new URL(m.group(1)).openStream(), Paths.get(out + UUID.randomUUID() + “.jpg”));
System.out.println(“已下載:”+j++);
}
}
}
}
Java爬蟲方向怎麼樣?
截止到 2007 年底,Internet 上網頁數量超出 160 億個,研究表明接近 30%的頁面是重複的;動態頁面的存在:客戶端、伺服器端腳本語言的應用使得指向相同 Web 信息的 URL 數量呈指數級增長。 上述特徵使得網路爬蟲面臨一定的困難,主要體現在 Web 信息的巨大容量使得爬蟲在給定時間內只能下載少量網頁。 Lawrence 和 Giles 的研究表明沒有哪個搜索引擎能夠索引超出 16%的Internet 上 Web 頁面,即使能夠提取全部頁面,也沒有足夠的空間來存儲 [1] 。
為提高爬行效率,爬蟲需要在單位時間內儘可能多的獲取高質量頁面,是它面臨的難題之一。 當前有五種表示頁面質量高低的方式[1]:Similarity(頁面與爬行主題之間的相似度)、Backlink(頁面在 Web 圖中的入度大小)、PageRank(指向它的所有頁面平均權值之和)、Forwardlink(頁面在 Web 圖中的出度大小)、Location(頁面的信息位置);Parallel(並行性問題)[3]。 為了提高爬行速度,網路通常會採取並行爬行的工作方式,隨之引入了新的問題:重複性(並行運行的爬蟲或爬行線程同時運行時增加了重複頁面)、質量問題(並行運行時,每個爬蟲或爬行線程只能獲取部分頁面,導致頁面質量下降)、通信帶寬代價(並行運行時,各個爬蟲或爬行線程之間不可避免要進行一些通信)。 並行運行時,網路爬蟲通常採用三種方式:獨立方式(各個爬蟲獨立爬行頁面,互不通信)、動態分配方式(由一個中央協調器動態協調分配 URL 給各個爬蟲)、靜態分配方式(URL 事先劃分給各個爬蟲) [1] 。
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();
}
}
原創文章,作者:KAQRV,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/317325.html