python利用高德接口,爬取武汉地区的POI--一个不太成熟的BUG,程序总是跑着跑着就假死了。
生活随笔
收集整理的這篇文章主要介紹了
python利用高德接口,爬取武汉地区的POI--一个不太成熟的BUG,程序总是跑着跑着就假死了。
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
說明
1.遇到的問題
可是爬取過程中總是不順利,程序總是爬著爬著就不動了,有時爬幾千條假死,有時爬幾萬條假死。數(shù)據(jù)庫中沒有新數(shù)據(jù)增加,程序也不報錯,也不中止。CPU,內(nèi)存占用也不高,硬盤中也還有空間,現(xiàn)在是實在不知道如何解決了。所以想讓請教一番。
2.需求背景
畢業(yè)設(shè)計需要用到一些城市的POI數(shù)據(jù),本著自己動手豐衣足食的原則,就從自己寫了段python代碼從高德地圖爬取POI數(shù)據(jù)。
3.高德獲取POI數(shù)據(jù)接口說明
多邊形搜索API接口,請求方式gethttps://restapi.amap.com/v3/place/polygon? //請求參數(shù):polygon:如果多邊形為矩形,則需要左上,右下經(jīng)緯度坐標(biāo) 左上角:113.705304,31.366201 右下角:115.089744,29.974252 以上為例,polygon = 113.705304,31.366201|115.089744,29.974252types=010000:POI數(shù)據(jù)的地物類型 ,比如汽車服務(wù),居民住宅等offset=10,每頁返回的數(shù)據(jù)量,最大為25page=1,頁碼從0開始,第0頁和第1頁相同,最大100 補充:接口文檔說一個區(qū)域最多1000個數(shù)據(jù),實測只有800多數(shù)據(jù)。4.代碼思路
由于一個區(qū)域只能獲取800多數(shù)據(jù)。
因此當(dāng)對一個矩形區(qū)域進行爬取時,如果返回的數(shù)據(jù)大于800,則認(rèn)為該區(qū)域的POI數(shù)據(jù)超過接口規(guī)定上限,對該區(qū)域進行四等分,然后再逐個進行爬取。如果返回的數(shù)據(jù)小于800,則認(rèn)為已經(jīng)獲取了該區(qū)域所有的POI,將這些POI寫入mysql數(shù)據(jù)庫。代碼
運行環(huán)境
IDE:pycharm3.3
環(huán)境:python3.6
系統(tǒng):64bit win10
內(nèi)存:16G
CPU:i7 7700hq
數(shù)據(jù)庫:mysql
源碼
import requests import pymysql import time import math import socket''' https://restapi.amap.com/v3/place/polygon?polygon=113.705304,31.366201|115.089744,29.974252&key=10518669c9fd0a0532e41189d61e1e9b&extensions=all&types=010000&offset=10&page=90 ''' # 初始區(qū)域的經(jīng)緯度 lon_l = 113.705304 lan_l = 31.366201 lon_r = 115.089744 lan_r = 29.974252# 要爬取POI的類型 types = '010000|020000|030000|040000|050000|060000|' \'070000|080000|090000|100000|110000|120000|' \'130000|140000|150000|160000|170000|180000|' \'190000|200000|210000|220000|230000|240000|' \'970000|990000'# 獲取POI的接口 url = 'https://restapi.amap.com/v3/place/polygon?' \'polygon={lon_l},{lan_l}|{lon_r},{lan_r}' \'&key=10518669c9fd0a0532e41189d61e1e9b&extensions=all' \'&types={types}&offset=25&page={page}'# point class Point:"""用經(jīng)緯度來描述一個點"""def __init__(self, lon, lan):self.lon = lon # 經(jīng)度self.lan = lan # 緯度# area class Rectangle:"""用左上角的經(jīng)緯度和右下角的經(jīng)緯度描述一個矩形區(qū)域"""def __init__(self, p_l, p_r):self.p_l = p_l # 左上角的點self.p_r = p_r # 右下角的點# 初始矩形的左上點和右下點 p_l = Point(lon_l,lan_l) p_r = Point(lon_r,lan_r)# 初始矩形,內(nèi)含兩點,左上,右下 rec = Rectangle(p_l,p_r)''' 打開一個URL,獲取返回信息 ''' def open_html(real_url):NET_STATUS=Falsewhile not NET_STATUS:try:data = requests.get(real_url).json()return dataexcept socket.timeout:print("NET_STATURS IS NOT GOOD")NET_STATUS=Falseexcept :print("OTHER WRONG")# 把一個區(qū)域的POI點存進數(shù)據(jù)庫 def get_pois(rec,url,data_count):url = url.format(lon_l = rec.p_l.lon , lan_l = rec.p_l.lan ,lon_r = rec.p_r.lon , lan_r = rec.p_r.lan ,types = types,page="{page}")f_url = open("url.txt","a",encoding="UTF-8")data= open_html(url.format(page=0))if data["status"] == "1":# 執(zhí)行到這里,說明url中含有poi數(shù)據(jù),下面開始爬取all_page=math.ceil(data_count/25)for page in range(all_page):try:# 從第1頁開始到第最后一頁url_real = url.format(page = page+1)f_url.write(url_real+'\n')data = open_html(url_real)if data["status"] == "1" : # 判斷第page+1頁是否有內(nèi)容pois = data["pois"]# 將數(shù)據(jù)儲存在數(shù)據(jù)庫# 優(yōu)化點:db先創(chuàng)建好,一次用完不關(guān),最后再關(guān)global db_globaldb = db_globalcursor = db.cursor()str_sql = 'insert into t_poi(id,name,address,typecode,lon,lan,pcode,pname,citycode,cityname,adcode,adname) ' \'values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'count=0for poi in pois:try:count += 1value = [poi['id'], poi['name'], poi["address"], poi['typecode'],poi['location'].split(',')[0], poi['location'].split(',')[1],poi['pcode'], poi['pname'], poi['citycode'], poi['cityname'], poi['adcode'], poi['adname']]if [] in value:value[value.index([])]=''try:cursor.execute(str_sql,value)db.commit()except:Exception# 打印日志文件f=open("wrong.txt",'a',encoding="UTF-8")time_fomat = '%Y-%m-%d %X'time_current = time.strftime(time_fomat)f.write(time_current+ ' 第{page}頁,第{index}個出錯\n'.format(page=page,index=count))except:passcursor.close()except:pass#檢測器 run_count = 0# 爬取,分析一個區(qū)域的POI數(shù)量,多于800則將區(qū)域四等分,并遞歸,低于800則進行爬取 def crawl_pois(rec,url):# 計算進行了幾次分析的計數(shù)器,判斷程序是否卡死global run_count;run_count += 1;f_count = open("count.txt",'a',encoding="UTF-8");f_count.write("這是第{_count}次運行分析一個區(qū)域\n".format(_count=run_count))# 根據(jù)矩形區(qū)域的經(jīng)緯度坐標(biāo),拼接urlurl_real = url.format(lon_l=rec.p_l.lon, lan_l=rec.p_l.lan,lon_r=rec.p_r.lon, lan_r=rec.p_r.lan,types=types, page="{page}")# 獲取url返回的數(shù)據(jù)data = open_html(url_real.format(page=0))if data["status"] == "1":# 執(zhí)行到這里,說明url中含有poi數(shù)據(jù),下面開始判斷區(qū)域POI數(shù)量data_count = int(data['count'])if data_count> 800:# 如果區(qū)域POI數(shù)據(jù)大于800則進行四等分rec_A = Rectangle(Point(0,0),Point(0,0))rec_B = Rectangle(Point(0,0),Point(0,0))rec_C = Rectangle(Point(0,0),Point(0,0))rec_D = Rectangle(Point(0,0),Point(0,0))# 經(jīng)緯度差lon_d = (rec.p_r.lon - rec.p_l.lon)/2lan_d = (rec.p_l.lan - rec.p_r.lan)/2# 計算每個小矩形的左上點,和右下點rec_A.p_l.lon = float(format(rec.p_l.lon,'6f'))rec_A.p_l.lan = float(format(rec.p_l.lan,'6f'))rec_A.p_r.lon = float(format(rec.p_l.lon + lon_d,'6f'))rec_A.p_r.lan = float(format(rec.p_r.lan + lan_d,'6f'))rec_B.p_l.lon = float(format(rec.p_l.lon + lon_d,"6f"))rec_B.p_l.lan = float(format(rec.p_l.lan,"6f"))rec_B.p_r.lon = float(format(rec.p_r.lon,"6f"))rec_B.p_r.lan = float(format(rec.p_r.lan + lan_d,"6f"))rec_C.p_l.lon = float(format(rec.p_l.lon,"6f"))rec_C.p_l.lan = float(format(rec.p_r.lan + lan_d,"6f"))rec_C.p_r.lon = float(format(rec.p_l.lon + lon_d,"6f"))rec_C.p_r.lan = float(format(rec.p_r.lan,"6f"))rec_D.p_l.lon = float(format(rec.p_l.lon + lon_d,"6f"))rec_D.p_l.lan = float(format(rec.p_r.lan + lan_d,"6f"))rec_D.p_r.lon = float(format(rec.p_r.lon,"6f"))rec_D.p_r.lan = float(format(rec.p_r.lan,"6f"))recs = []recs.append(rec_A)recs.append(rec_B)recs.append(rec_C)recs.append(rec_D)# 對四個小矩形分別進行爬取,這里使用遞歸for rec_s in recs :# 如果一個區(qū)域出現(xiàn)異常,就進行下個區(qū)域try:crawl_pois(rec_s,url)except:passelse:# 如果該矩形區(qū)域poi點的數(shù)量少于800就進行爬取get_pois(rec,url,data_count)else:print("出錯")''' 下面是程序的入口 ''' # 創(chuàng)建一個全局的連接 db_global = pymysql.connect("localhost", "root", "111111", "poi")# 對一個矩形進行爬取分析,這里是對武漢地區(qū)的左上角和右下角的經(jīng)緯度圍成的矩形進行爬取 crawl_pois(rec,url)# 關(guān)閉數(shù)據(jù)庫 db_global.close()代碼的思路我自我感覺沒什么大問題,遞歸也有出口,就是程序跑著跑著就假死了,我也不能確定到底是哪里有問題,路過的大手子們
總結(jié)
以上是生活随笔為你收集整理的python利用高德接口,爬取武汉地区的POI--一个不太成熟的BUG,程序总是跑着跑着就假死了。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PD-QC-AFC多协议诱骗芯片《LDR
- 下一篇: Android 地图导航调用百度地图、高