經緯度轉地址

      在〈經緯度轉地址〉中尚無留言

OpenStreemMap Nominatim

使用 requests 連線到 https://nominatim.openstreetmap.org 查詢。

免費方案 : 每日查詢次數無限制
連線速度 : 自動限制一秒一次
api key : 不需註冊,亦不需 api key
地址資訊 : 較為詳細

請先安裝套件

pip install requests

完整代碼如下

🔒 底下內容僅限會員閱讀。

立即登入

上述的 email 隨便填入即可,它不會檢查此 email 是否正確。而且不需暫緩執行,因為會自動限制一秒後才會回應。

geopy 套件

使用 geopy 套件,由 OpenStreetMap 提供的 Nominatim 反向地理編碼查詢,完全不需付費,每秒限制只能查詢一次,所取得的地址資料沒有上述的方法詳細。

免費方案 : 每日查詢次數無限制
連線速度 : 自動限制一秒一次
api key : 不需註冊,亦不需 api key
地址資訊 : 較為簡易

請先安裝如下套件

pip install geopy

完整代碼如下

🔒 底下內容僅限會員閱讀。

立即登入

上述的 email 隨便填入即可,它不會檢查此 email 是否正確。而且不需暫緩執行,因為會自動限制一秒後才會回應。

使用 Nominatim 網頁

可到如下網址查詢 https://nominatim.openstreetmap.org/ui/reverse.html。修改網頁上的 lat 及 lon,然後按下 Search 就可以搜尋地址。

這個網頁也可以寫成 selenium 來爬蟲,但爬蟲的速度不能太快,否則很容易被封鎖 ip。

請先安裝如下套件。

pip install selenium webdriver-manager mysql-connector-python

完整 selenium 代碼如下。

🔒 底下內容僅限會員閱讀。

立即登入

LocationIQ

LocationIQ 是另一種查詢方式,地址資訊較不準確。

免費方案 : 每日限制查詢 5000次
連線速度 : 每秒不可超過二次
api key : 需註冊並取得 api key
地址資訊 : 較為簡易

請到 https://locationiq.com/ 註冊,登入後按下「Access Tokens」即可取得 api。

完整代碼如下

🔒 底下內容僅限會員閱讀。

立即登入

Google Map 暴力爬蟲

此法已失效了,僅作記錄。

將經緯度轉換地址,目前就只有 Google 的 Geocoding API 可以使用,但 Geocoding API 是需要付費的,所以本範例使用 Google Map 暴力爬蟲程式,完全不需付費。

底下的代碼,故意拼命的查,每當查詢到 170筆左右,就會被 Google Map 認定為機器人而彈出確認的畫面。Google Map 有一個特性,就算被認定為機器人,只要關掉瀏覽器,再重新啟動即可,不會鎖 IP。

所以本程式故意不使用 time.sleep(2),當被判定為機器人時,address 返回 None 值。主程式收到 address 為 None ,就關閉瀏覽器並重新啟動,繼續拼命的查,夠暴力吧! 因為本人每天要查上萬筆資料,每筆停留2秒,那還得了。

希望 Google 不要看到此篇文章,不然又想出啥防制方法,那就頭大了。

#pip install selenium webdriver-manager
import mysql.connector as mysql
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support import expected_conditions as EC

def dms(x):#經緯度轉度分秒
    #1度 : 60分
    #1分 : 60秒
    d=int(x)
    m=int((x-d)*60)
    s=(x-d)*3600-m*60
    return f'{d}°{m}\'{s}"'
def getAddress(lat, lng):
    lng=dms(lng)
    lat=dms(lat)
    browser.get(f"https://www.google.com/maps/place/{lat}N+{lng}E")
    try:
        WebDriverWait(browser, 3).\
            until(EC.presence_of_element_located(
                (By.ID,'searchbox-searchbutton')
            )
        )
        node=browser.find_element(
            By.XPATH,value='//meta[@itemprop="description"]'
        )
        address=node.get_attribute("content")
        return address[3:]
    except:
        print("被判定為機器人了,重啟瀏覽器中...")
        return None
conn=mysql.connect(host="localhost",
                   user="登入資料庫帳號",
                   password="登入資料庫密碼",
                   database="資料庫")
cursor=conn.cursor()
cursor.execute("select * from covid19")
rs=cursor.fetchall()
conn.close()
ops=Options()
ops.add_argument('--headless')
ops.add_experimental_option('detach',False)
service=Service(ChromeDriverManager().install())
browser=webdriver.Chrome(service=service, options=ops)
total=len(rs)
conn=mysql.connect(host="localhost",user="thomas", password="xxx", database="cloud")
cursor=conn.cursor()
for i, r in enumerate(rs):
    address=None
    while address is None:
        address=getAddress(r[3], r[2])
        if address is None:#沒取得地址,因為 google map 判定本程式是機器人
            #被判定是機器人時,並不會鎖 ip, 只要瀏覽器重開,就可以繼續爬蟲
            browser.close()
            browser=webdriver.Chrome(service=service, options=ops)
    print(f"{i+1}/{total} {r[2]:.8f},{r[3]:.8f} : {address}")
    cmd=f"insert into 地址 (經度, 緯度, 地址) values ({r[2]}, {r[3]}, '{address}')"
    cursor.execute(cmd)
    conn.commit()
conn.close()

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *