作了一個爬取api的類.能夠獲取2017全國行政區域.html
效果圖:mysql
首先這個api在阿里雲市場 是免費的.每一個人均可以用.
地址在這裏git
要先註冊阿里雲,而後購買他這個,一次只能買1000.你能夠買三四次,應該就能夠所有下載完畢了.github
1.初始化curl_multi 並將curl 句柄添加進去. 2.執行全部的curl句柄 3.處理全部的curl返回的結果
那個api是有2種接口,第一是經過名稱獲取城市的信息,第二是經過父城市id獲取全部子城市
由於父城市id咱們不知道,因此第一步必須是經過名稱獲取城市的信息
定義數組 全國全部省級行政區(共34個)sql
第一步是獲取這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(); }
我半年前作爬蟲的時候 爲了搞清楚這個百度谷歌都查 就是沒有找到滿意的答案.
後來乾脆就這樣隨便寫了.效果還能夠.
其中 這一句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上也有.但願對你們有幫助.