PHP爬蟲 -- 010 做業解析

做業回顧

  • 爬取分類下的圖書名和對應價格, 保存到books.txt
  • books.toscrape.com
  • 最終效果...

做業解析

  • 兩個難度
  • 簡單難度
    • 爬取分類和分類下的第一頁的數據, 不包括分頁
    • 所須要的知識已經講過, 不須要額外的知識
  • 中等難度
    • 爬取分類和分類下的全部數據, 須要判斷總頁數
    • 須要額外的知識, 字符串切割/截取

做業分析

  1. 先獲取分類的名稱和url
  2. 再經過url獲取分類下的圖書信息
  3. 注意分類的url須要拼接

小彩蛋: 運行前清屏

代碼解析-簡單難度-帶註釋

<?php


/** * _ooOoo_ * o8888888o * 88" . "88 * (| -_- |) * O\ = /O * ____/`---'\____ * .' \\| |// `. * / \\||| : |||// \ * / _||||| -:- |||||- \ * | | \\\ - /// | | * | \_| ''\---/'' | | * \ .-\__ `-` ___/-. / * ___`. .' /--.--\ `. . __ * ."" '< `.___\_<|>_/___.' >'"". * | | : `- \`.;`\ _ /`;.`/ - ` : | | * \ \ `-. \_ __\ /__ _/ .-` / / * ======`-.____`-.___\_____/___.-`____.-'====== * `=---=' * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * 佛祖保佑 永無BUG */

require 'vendor/autoload.php';
use QL\QueryList;
// 生成一個querylist對象
$ql = new QueryList();

/* * @Description:獲取分類 * @params: 主頁url * @return: 二維數組, 包括分類名稱, 分類url */
function get_category($url) {
    global $ql;

    $data = $ql->get($url)->rules([
        "category_name" => ['#default > div > div > div > aside > div.side_categories > ul > li > ul > li > a', 'text'],
        "category_url" => ['#default > div > div > div > aside > div.side_categories > ul > li > ul > li > a', 'href'],
    ])->queryData();
    // 把分類的連接地址補全
    foreach ($data as $key => $value) {
        $value['category_url'] = $url . $value['category_url'];
        $data[$key] = $value;
    }
    return $data;
}

/* * @Description: 獲取分類下的圖書信息 * @param: 分類的url * @return: 二維數組, 包括圖書名稱, 圖書價格 */
function get_book($url) {
    global $ql;

    $data = $ql->get($url)->rules([
        "book_name" => ['#default > div > div > div > div > section > div:nth-child(2) > ol > li > article > h3 > a', 'title'],
        "book_price" => ['#default > div > div > div > div > section > div:nth-child(2) > ol > li> article > div.product_price > p.price_color', 'text'],
    ])->queryData();

    return $data;

}

/* * @Description: 生成最終的數組 * @param: 從分類獲取的數組 * @return: 最終整合了圖書信息的數組 */
function make_array($data) {
    foreach ($data as $key => $value) {
        echo $value['category_url']."\n";
        $value['books'] = get_book($value['category_url']);
        $data[$key] = $value;
    }
    return $data;
}
/* * @Description: 寫入txt文件 * @param: 整合好的數組 * @return: 沒有返回值 */ 
function make_txt($data) {
    $txt_obj = fopen('books.txt', 'w+');
    foreach ($data as $key => $value) {
        $category_name = $value['category_name'];
        fwrite($txt_obj, "{$category_name}\n");
        foreach ($value['books'] as $k => $book) {
            $book_name = $book['book_name'];
            $book_price = $book['book_price'];
            fwrite($txt_obj, "\t\"{$book_name}\" {$book_price}\n");
        }
    }
    fclose($txt_obj);
}


// 爬取並整合數據
$data = make_array(get_category('http://books.toscrape.com/'));
// 把數據寫入books.txt
make_txt($data);
複製代碼

代碼解析-中等難度-帶註釋

<?php


/** * _ooOoo_ * o8888888o * 88" . "88 * (| -_- |) * O\ = /O * ____/`---'\____ * .' \\| |// `. * / \\||| : |||// \ * / _||||| -:- |||||- \ * | | \\\ - /// | | * | \_| ''\---/'' | | * \ .-\__ `-` ___/-. / * ___`. .' /--.--\ `. . __ * ."" '< `.___\_<|>_/___.' >'"". * | | : `- \`.;`\ _ /`;.`/ - ` : | | * \ \ `-. \_ __\ /__ _/ .-` / / * ======`-.____`-.___\_____/___.-`____.-'====== * `=---=' * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * 佛祖保佑 永無BUG */

require 'vendor/autoload.php';
use QL\QueryList;
// 生成一個querylist對象
$ql = new QueryList();

/* * @Description:獲取分類 * @params: 主頁url * @return: 二維數組, 包括分類名稱, 分類url */
function get_category($url) {
    global $ql;

    $data = $ql->get($url)->rules([
        "category_name" => ['#default > div > div > div > aside > div.side_categories > ul > li > ul > li > a', 'text'],
        "category_url" => ['#default > div > div > div > aside > div.side_categories > ul > li > ul > li > a', 'href'],
    ])->queryData();
    // 把分類的連接地址補全
    foreach ($data as $key => $value) {
        $value['category_url'] = $url . $value['category_url'];
        $data[$key] = $value;
    }
    return $data;
}

/* * @Description: 獲取分類下的圖書信息, 若是有下一頁, 遞歸獲取 * @param: 分類的url * @return: 二維數組, 包括圖書名稱, 圖書價格 */
function get_book($url) {
    global $ql;
    echo $url."\n";
    $data = $ql->get($url)->rules([
        "book_name" => ['#default > div > div > div > div > section > div:nth-child(2) > ol > li > article > h3 > a', 'title'],
        "book_price" => ['#default > div > div > div > div > section > div:nth-child(2) > ol > li> article > div.product_price > p.price_color', 'text'],
    ])->queryData();
    // 獲取下一頁按鈕的href, 用來拼接下一頁的完整url
    $next = has_next($url);
    if($next){
        // 生成完整url
        $tmp_arr = explode('/',$url);
        $tmp_arr[count($tmp_arr)-1] = $next;
        $next_url = implode('/',$tmp_arr);
        // 調用get_book(), 把返回的數據和當前數據合併
        $data = array_merge($data,get_book($next_url));
    }
    return $data;
}
/* * @Description: 判斷有沒有下一頁 * @param: 當前url * @return: 若是有返回按鈕的href, 若是沒有, 返回空字符串 */ 
function has_next($url){
    global $ql;
    $res = $ql->get($url)->find('#default > div > div > div > div > section > div:nth-child(2) > div > ul > li.next > a')->href;
    return $res;
}
/* * @Description: 生成最終的數組 * @param: 從分類獲取的數組 * @return: 最終整合了圖書信息的數組 */
function make_array($data) {
    foreach ($data as $key => $value) {
        echo $value['category_url']."\n";
        $value['books'] = get_book($value['category_url']);
        $data[$key] = $value;
    }
    return $data;
}
/* * @Description: 寫入txt文件 * @param: 整合好的數組 * @return: 沒有返回值 */ 
function make_txt($data) {
    $txt_obj = fopen('books.txt', 'w+');
    foreach ($data as $key => $value) {
        $category_name = $value['category_name'];
        fwrite($txt_obj, "{$category_name}\n");
        foreach ($value['books'] as $k => $book) {
            $book_name = $book['book_name'];
            $book_price = $book['book_price'];
            fwrite($txt_obj, "\t\"{$book_name}\" {$book_price}\n");
        }
    }
    fclose($txt_obj);
}


// 爬取並整合數據
$data = make_array(get_category('http://books.toscrape.com/'));
// 把數據寫入books.txt
make_txt($data);
複製代碼

下一節

相關文章
相關標籤/搜索