1. 程式人生 > >爬蟲任務二:爬取(用到htmlunit和jsoup)通過百度搜索引擎關鍵字搜取到的新聞標題和url,並保存在本地文件中(主體借鑒了網上的資料)

爬蟲任務二:爬取(用到htmlunit和jsoup)通過百度搜索引擎關鍵字搜取到的新聞標題和url,並保存在本地文件中(主體借鑒了網上的資料)

標題 code rgs aps snap one reader url 預處理

采用maven工程,免著到處找依賴jar包

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zhaowu</groupId>
    <artifactId>pachong01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <!-- https://
mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency> <!-- https://
mvnrepository.com/artifact/org.jsoup/jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.2</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/cn.edu.hfut.dmic.webcollector/WebCollector --> <dependency> <groupId>cn.edu.hfut.dmic.webcollector</groupId> <artifactId>WebCollector</artifactId> <version>2.71</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <!-- https://mvnrepository.com/artifact/net.sourceforge.htmlunit/htmlunit --> <dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit</artifactId> <version>2.29</version> </dependency> </dependencies> </project>

直接上代碼RenWu.class

package com.zhaowu.renwu2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

public class RenWu {
    // 搜索頁數
    private static int N = 6;
    // 搜索關鍵詞
    private static String keyWord = "爬蟲";
    // 第一頁搜索結果
    private static HtmlPage firstBaiduPage;
    // Baidu對應每個搜索結果的第一頁第二頁第三頁等等其中包含“&pn=1”,“&pn=2”,“&pn=3”等等,
    // 提取該鏈接並處理可以獲取到一個模板,用於定位某頁搜索結果
    private static String template = "";

    public static void main(String[] args) {
        goSearch(N, keyWord);
    }

    private static void goSearch(final int n, final String keyWord) {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                // 頁數
                int x = n;
                System.out.println("爬取百度關於關鍵字“" + keyWord + "”搜索結果的前" + x + "頁");
                FileUtil.toFile("爬取百度關於關鍵字“" + keyWord + "”搜索結果的前" + x + "頁\n");
                
                //1.獲取並輸出第一頁百度查詢內容
                Elements firstElementsLink = null;
                try {
                    firstElementsLink = getFirstPage(keyWord);
                } catch (Exception e) {
                    e.printStackTrace();
                } 
                for (Element link : firstElementsLink) {
                    // 鏈接url
                    String linkHref = link.attr("href");
                    // 鏈接標題
                    String linkText = link.text();
                    if(linkHref.length() > 13 & linkText.length() > 4) {
                        String content = "鏈接url: " + linkHref + "\n\t鏈接標題: " + linkText + "\n";
                        System.out.println(content);
                        FileUtil.toFile(content);
                    }
                }
                
                //2.讀取第二頁及之後頁面預處理
                // 以firstBaiduPage作為參數,定義template,即網頁格式。
                nextHref(firstBaiduPage);
                
                //3.獲取百度第一頁之後的搜索結果
                for(int i = 1; i< x; i++) {
                    System.out.println("\n---------百度搜索關鍵字“" + keyWord + "”第" + (i + 1) + "頁結果------");
                    FileUtil.toFile("\n---------百度搜索關鍵字“" + keyWord + "”第" + (i + 1) + "頁結果------" + "\n");
                    // 根據已知格式修改生成新的一頁的鏈接
                    String tempURL = template.replaceAll("&pn=1", "&pn=" + i + "");
                    // 顯示該搜索模板
                    System.out.println("\t該頁地址為:" + tempURL);
                    RenWu renWu = new RenWu();
                    // 實現摘取網頁源碼
                    String htmls = renWu.getPageSource(tempURL, "utf-8");
                    // 網頁信息轉換為jsoup可識別的doc模式
                    Document doc = Jsoup.parse(htmls);
                    // 摘取該頁搜索鏈接
                    Elements links = doc.select("a[data-click]");
                    // 該處同上getFirstPage的相關實現
                    for (Element link : links) {
                        // 鏈接url
                        String linkHref = link.attr("href");
                        // 鏈接標題
                        String linkText = link.text();
                        if(linkHref.length() > 13 & linkText.length() > 4) {
                            String content = "鏈接url: " + linkHref + "\n\t鏈接標題: " + linkText + "\n";
                            System.out.println(content);    
                            FileUtil.toFile(content);
                        }
                    }
                }
            }
        });
        thread.start();
    }
    
    public String getPageSource(String pageURL, String encoding) {
        // 輸入:url鏈接&編碼格式
        // 輸出:該網頁內容
        StringBuffer sb = new StringBuffer();
        try {
            // 構建一URL對象
            URL url = new URL(pageURL);
            // 使用openStream得到一輸入流並由此構造一個BufferedReader對象
            InputStream in = url.openStream();
            InputStreamReader ir = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(ir);
            String line;
            while((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /*
     * 獲取百度搜索第一頁內容
     */
    public static Elements getFirstPage(String keyWord) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
        //設置瀏覽器的User-Agent
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52);
        // HtmlUnit對JavaScript的支持不好,關閉之
        webClient.getOptions().setJavaScriptEnabled(false);
        // HtmlUnit對CSS的支持不好,關閉之
        webClient.getOptions().setCssEnabled(false);
        // 百度搜索首頁頁面
        HtmlPage htmlPage = webClient.getPage("http://www.baidu.com/");
        // 獲取搜索輸入框並提交搜索內容(查看源碼獲取元素名稱)
        HtmlInput input = htmlPage.getHtmlElementById("kw");
        // 將搜索詞模擬填進百度輸入框(元素ID如上)
        input.setValueAttribute(keyWord);
        // 獲取搜索按鈕並點擊
        HtmlInput btn = htmlPage.getHtmlElementById("su");
        // 模擬搜索按鈕事件,獲取第一頁的html內容
        firstBaiduPage = btn.click();
        // 將獲取到的百度搜索的第一頁信息輸出
        // 通過page.asXml()來獲取百度首頁的源代碼,
        // 通過page.asTest()來獲取頁面的文字
        String content = firstBaiduPage.asXml().toString();
        // 轉換為Jsoup識別的doc格式
        Document doc = Jsoup.parse(content);
        System.out.println("---------百度搜索關鍵字“" + keyWord + "”第1頁結果--------");
        FileUtil.toFile("---------百度搜索關鍵字“" + keyWord + "”第1頁結果--------" + "\n");
        // 返回包含類似<a......data-click=" "......>等的元素
        Elements firstElementsLink = doc.select("a[data-click]");
        // 返回此類鏈接,即第一頁的百度搜素鏈接
        return firstElementsLink;
    }
    
    /*
     * 獲取下一頁地址
     */
    public static void nextHref(HtmlPage firstBaiduPage) {
        
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52);
        webClient.getOptions().setJavaScriptEnabled(false);
        webClient.getOptions().setCssEnabled(false);
        // 獲取到百度第一頁搜索的底端的頁碼的html代碼
        String morelinks = firstBaiduPage.getElementById("page").asXml();
        // 轉換為Jsoup識別的doc格式
        Document doc = Jsoup.parse(morelinks);
        // 提取這個html中的包含<a href=""....>的部分
        Elements links = doc.select("a[href]");
        // 設置只取一次每頁鏈接的模板格式
        boolean getTemplate = true;
        for (Element e : links) {
            // 將提取出來的<a>標簽中的鏈接取出
            String linkHref = e.attr("href");
            if(getTemplate) {
                // 補全模板格式
                template = "http://www.baidu.com" + linkHref;
                getTemplate = false;
            }
        }
    }
}

導出到本地文件(末尾追加)的封裝方發類FileUtil.class:

package com.zhaowu.renwu2;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class FileUtil {
    public static void toFile (String content) {
        File file = null;
        FileWriter fw = null;
        file = new File("/home/acer/桌面/aaa");
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            fw = new FileWriter(file,true);
            fw.write(content);//向文件中復制內容
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fw != null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

爬蟲任務二:爬取(用到htmlunit和jsoup)通過百度搜索引擎關鍵字搜取到的新聞標題和url,並保存在本地文件中(主體借鑒了網上的資料)