php 爬蟲程序 爬取有用的免費API

作了一個爬取api的類.能夠獲取2017全國行政區域.html

git: https://github.com/buffge/loa...

效果圖:mysql

clipboard.png

差很少有40000多行 只要90秒就能夠爬完

首先這個api在阿里雲市場 是免費的.每一個人均可以用.
地址在這裏git

要先註冊阿里雲,而後購買他這個,一次只能買1000.你能夠買三四次,應該就能夠所有下載完畢了.github

爬蟲思路:

1.初始化curl_multi 並將curl 句柄添加進去.
2.執行全部的curl句柄
3.處理全部的curl返回的結果

那個api是有2種接口,第一是經過名稱獲取城市的信息,第二是經過父城市id獲取全部子城市
由於父城市id咱們不知道,因此第一步必須是經過名稱獲取城市的信息
定義數組 全國全部省級行政區(共34個)sql

clipboard.png

爬蟲運行順序

第一步是獲取這34個省(level=1)的信息.
第二步就是循環34次 每次循環查詢當前城市的全部子城市(level=2)
第三步就是循環(level=2)城市的個數次,而後查詢level=3城市的信息
第四步就是循環(level=3)城市的個數,查詢level=4城市的信.最大就到level4 也就是鄉鎮一級
有的城市連level3都沒有,沒有的狀況下就會continue

代碼塊分析

public
            function start() {
//啓動一個mcurl
        $mh = curl_multi_init();
        $orinigal_chs = [];
//初始化mcurl 並添加必定數量(最高爲所有或者最大併發)curl進去
        $this->curlMultiInit($mh, $orinigal_chs);
//執行全部的curl句柄並返回全部curl句柄數組
        $chs = $this->curlMultiExec($mh, $orinigal_chs);
//獲取全部的curl返回的結果
        $res = $this->getCurlResult($chs);
//若是爲正常結果
        if (is_array($res)) {
//對每個curl結果進行處理
            $this->dataHandle($res);
        }
        else {
//輸出錯誤信息
            echo "當前列表中全部城市都沒有子城市.\n";
        }
    }

這是啓動方法全部的操做都在裏面.這裏使用的是多線程爬蟲.若是不會的能夠百度.
核心的代碼就是最後一個對curl結果進行處理的方法;
主要作的內容是插入上一次獲取到的城市信息到數據庫
接着對每個獲取到的城市進行子城市 查詢 也就是上面所說的循環
因爲我是個菜鳥,我有很久沒用過mysql了,不知道爲何這裏的affected_rows爲何老是等於-1.
知道的 能告訴我一下就行了.
以下:數據庫

protected
            function dataHandle(array $res) {
        $mysqli = new \mysqli($this->host, $this->name, $this->pwd, $this->dbname);
        foreach ($res as $k => $v) {
            $mixedInfo = json_decode($v[0]);
            $cityInfo = $mixedInfo->showapi_res_body->data;
            $citysLength = count($cityInfo);
            $sql = "INSERT INTO `allcitys` ( `provinceId`, `simpleName`, `lon`, `areaCode`, `cityId`, `remark`, `prePinYin`, `cid`, `pinYin`, `parentId`, `level`, `areaName`, `simplePy`, `zipCode`, `countyId`, `lat`, `wholeName`) VALUES ";
            $sql_values = '';
            for ($i = 0; $i < $citysLength; $i++) {
                $sql_values .= "('{$cityInfo[$i]->provinceId}', '{$cityInfo[$i]->simpleName}', '{$cityInfo[$i]->lon}', '{$cityInfo[$i]->areaCode}', '{$cityInfo[$i]->cityId}', '{$cityInfo[$i]->remark}', '{$cityInfo[$i]->prePinYin}', '{$cityInfo[$i]->id}',\"{$cityInfo[$i]->pinYin}\", '{$cityInfo[$i]->parentId}', '{$cityInfo[$i]->level}', '{$cityInfo[$i]->areaName}', '{$cityInfo[$i]->simplePy}', '{$cityInfo[$i]->zipCode}', '{$cityInfo[$i]->countyId}', '{$cityInfo[$i]->lat}', '{$cityInfo[$i]->wholeName}'),";
            }
            $sql_values = substr_replace($sql_values, '', -1);
            $sql .= $sql_values;
            $mysqli->query($sql);
//不知道爲何這裏的affect_rows 老是-1
//if ($mysqli->affected_rows == $citysLength) {
            if (1) {
                echo "{$citysLength}條數據添加成功\n";
                if ($this->level < 4) {
                    $temp_level = $this->level + 1;
                    for ($j = 0; $j < $citysLength; $j++) {
                        $tempearchCitysList[] = $cityInfo[$j]->id;
                    }
                    $config = [
                        'appcode'         => $this->appcode,
                        'level'           => $temp_level,
                        'amount'          => $citysLength,
                        'getInfo'         => self::SUB_LIST,
                        'searchCitysList' => $tempearchCitysList,
                        'host'            => $this->host,
                        'name'            => $this->name,
                        'pwd'             => $this->pwd,
                        'dbname'          => $this->dbname
                    ];
                    $subLoad = new self($config);
                    $tempearchCitysList = [];
                    $subLoad->start();
                }
            }
            else {
                echo $this->searchCitysList[$k] . "數據插入失敗!\n";
            }
        }
        $mysqli->close();

    }

比較難理解的代碼塊就是curl_multi那個方法

我半年前作爬蟲的時候 爲了搞清楚這個百度谷歌都查 就是沒有找到滿意的答案.
後來乾脆就這樣隨便寫了.效果還能夠.
其中 這一句json

$mrc = curl_multi_exec($mh, $active);api

表示執行$mh中全部的curl句柄.$active 表示當前還剩多少個沒有執行完畢.數組

$info = curl_multi_info_read($mh, $msgq);

這裏這句就是讀取$mh 已經執行完畢的內容若是$info爲真,表示這個curl句柄已經完成了,
而後咱們從這個info中讀取handle 也就是當前curl句柄.
若是$info 爲假那麼就延時1000微秒,由於執行太快 對cpu壓力很大. 多線程

由於我英語很差官方文檔看不懂,也沒有學過底層,這裏的不少東西都是我根據效果猜的.裏面若是有講錯來的地方請你們告訴我一下.

不單單是這個api ,其餘的api 也能夠經過這種思路去爬取.圖片站 小說站均可以這樣爬取.我半年前作過一個爬取圖片站的類.git上也有.但願對你們有幫助.

相關文章
相關標籤/搜索