Automatisation d'une recherche sur des informations géographiques telles que le réseau de magasins à l'aide de Python et de l'API Web

Quelque chose quoi

Nous avons automatisé l'analyse des ouvertures de magasins à l'aide de Python et de l'API Web (Google géocode). Les pièces automatisées sont les trois points suivants. ① Acquisition de l'adresse du magasin ② Obtenez la longitude et la latitude de l'adresse ③ Obtention de la distance depuis la longitude et la latitude

Cela vous permet, par exemple, de: Exemple 1) Enquête sur la redondance du propre magasin. Listez les magasins dans un rayon de 3 km lorsqu'ils sont consultés à partir d'un certain magasin. Exemple 2) Enquête sur la distance des magasins concurrents. Liste des autres magasins dans un rayon de 3 km lorsqu'ils sont consultés depuis un seul magasin.

Pour plus de concision, veuillez consulter ce référentiel. https://github.com/taiga518/automation-geo

Automated a research on geographical information such as store network using python and Web API. Automation includes the following three parts.

  1. Collecting address information
  2. Converting address information into latitude and longitude
  3. Converting longitude and latitude information into distance

You can also check my git repository: https://github.com/taiga518/automation-geo

Quel était le problème

Dans une analyse simple du réseau de magasins, il était nécessaire d'effectuer manuellement les étapes ① à ③ ci-dessus. ① Copiez l'adresse de chaque magasin depuis la page d'accueil. À ce moment, des erreurs et des oublis peuvent survenir. (2) (3) Je ne pense pas que vous vouliez la latitude et la longitude elles-mêmes, mais si vous voulez connaître la distance, vous deviez entrer manuellement l'adresse dans google maps etc. et mesurer la distance entre les points. Cela prendra un certain temps. Par exemple, si vous voulez connaître toutes les distances entre deux magasins dans 100 magasins, vous devez vérifier plus de 5000 voies (!), Ce qui n'est pas réaliste.

The most simple way to tackle with these task might be doing them manually. However, it would take unrealistically long time if number of stores you would like to check is high (eg. to check distance of all the pair of two stores from in total 100 stores, you need to check distance for more than 5000 times)

Ce que j'ai fait / ce que j'ai fait

Comme mentionné ci-dessus, trois programmes ont résolu le problème. As I mentioned earlier, I solved this issue with three programs.

① Acquisition de l'adresse du magasin / Collecte des informations d'adresse

Ce programme est un exemple concis d'un programme qui obtient automatiquement une adresse à partir de la liste de magasins sur la page d'accueil par grattage Web.

This program is a simple example of web scraping to get address information of shops automatically.

Code (Cliquez pour ouvrir)

get_address(example).py


"""" 
Just an example of simple web scraping.
Ceci est un exemple d'acquisition d'une adresse de magasin par web scraping.
"""

import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np


"""
Rondom company with many shops is set as an example.
Un exemple d'entreprise avec de nombreux magasins est la fenêtre Hoken. C'est fondamentalement la même chose pour les autres entreprises.
Homepage here : https://www.hokennomadoguchi.com/shop-list/
"""

urlName = "https://www.hokennomadoguchi.com/shop-list/"
url = requests.get(urlName)
soup = BeautifulSoup(url.content, "html.parser")


shop_name_list = []
address_list = []
# select finds class and id.Trouvez la classe ou l'identifiant avec select.
for elem in soup.select(".shop-link"):
    # find finds first tag appears.find recherchera la balise correspondante qui apparaît en premier.
    # get finds attributes.get obtient l'attribut (attribut).
    shop_url = "https://www.hokennomadoguchi.com" + elem.find("a").get("href")
    # contents breakdowns tags.le contenu décompose la balise et vous permet de sélectionner la partie ou l'attribut de la balise.
    shop_name = elem.find("a").select(".shop_name")[0].contents[0]
    print("--- "+ shop_name +" ---")
    url = requests.get(shop_url)
    soup_shop = BeautifulSoup(url.content, "html.parser")
    address = soup_shop.select(".item2")[0].contents[2].replace(" ","").replace("\u3000","").replace("\r","").replace("\n","")
    print(address)

    shop_name_list.append(shop_name)
    address_list.append(address)
    
    
df_madoguchi = pd.DataFrame([shop_name_list,address_list]).T
df_madoguchi.columns=["shop_name", "address"]

df_madoguchi.to_csv("madoguchi_address.csv", encoding='utf_8_sig')

② Conversion des informations d'adresse en latitude et longitude Ce programme utilise l'API google geocode pour obtenir automatiquement la latitude et la longitude d'une adresse (chaîne de caractères). This program is to get longitude and latitude from address(string) using google geocode API.

Code (Cliquez pour ouvrir)

get_lnglat_geocode.py


import json
import pandas as pd
import requests
import time

API_key = "XXXXX"
"""    
Veuillez noter que vous devrez obtenir vous-même la clé API.
Je ne pense pas que vous serez facturé pour votre fréquence d'utilisation personnelle, mais veuillez vérifier attentivement la liste de prix.
API key needs to be set to use google geocoding API. Follow the guidance here :
https://developers.google.com/maps/documentation/geocoding/overview
"""


def start_end_decolator(input_function):
    """Decolator to print start and end"""
    def return_function(*args, **kwargs):
        print("\n--------------start--------------")
        result = input_function(*args, **kwargs)
        print("\n---------------end---------------")
        return result
    return return_function

def progress_decolator(input_function):
    """Decolator to print * to show progress"""
    def return_function(*args, **kwargs):
        print("*", end="")
        result = input_function(*args, **kwargs)
        return result
    return return_function

@progress_decolator
def get_location(address):
    """ 
Utilisez le géocodage de Google pour obtenir la longitude et la latitude à partir de l'adresse.
    
    Get latitude and longitude using google geocoding API.
    API key needs to be set to use google geocodin API. Follow the guidance here : 
    https://developers.google.com/maps/documentation/geocoding/overview
    Check billing here: https://console.cloud.google.com/google/maps-apis/overview
    
    Input : address as text
        eg) "4-2-8 Parc Shiba, Minato-ku, Tokyo"
        
    Output : tupple of address(text), latitude(float), longitude(float)
        eg) ('4-chōme-2-8 Shibakōen, Minato City, Tōkyō-to 105-0011, Japan', 35.6585769, 139.7454506)
    """
    url = "https://maps.googleapis.com/maps/api/geocode/json?address=+"+address+"&key="+API_key
    result = requests.get(url)
    result_json = json.loads(result.text)
    formatted_address = result_json["results"][0]["formatted_address"]
    lat, lng = result_json["results"][0]["geometry"]["location"].values()
    return (formatted_address, lat, lng)


@start_end_decolator    
def add_location_info(input_df):
    """
Obtenez ci-dessus à partir d'une liste d'adresses multiples_Utilisez la fonction de localisation pour obtenir une liste des longitudes et des latitudes.
    
    Get lists of location information using get_location function.
    
    Input : dataframe with address information named address
    Output : dataframe with formatted_address, latitute, longitude columns
    """    
    
    formatted_address_list = []
    lat_list = []
    lng_list = []

    for i_row in range(len(input_df)):
        formatted_address, lat, lng = get_location(input_df.loc[i_row,"address"])
        formatted_address_list.append(formatted_address)
        lat_list.append(lat)
        lng_list.append(lng)
    
    output_df = input_df
    output_df["formatted_address"] = formatted_address_list
    output_df["latitude"] = lat_list
    output_df["longitude"] = lng_list
    return output_df



### main here

df = pd.read_csv("PATH.csv")
df = df[["name","address"]]
df_loc = add_location_info(df)
df_loc.to_csv("output.csv", encoding='utf_8_sig')


③ Conversion des informations de longitude et de latitude en distance Ce programme calcule automatiquement la distance entre deux points exprimée en latitude et longitude. This program is to calculate distance between two points described with longitude and latitude.

Code (Cliquez pour ouvrir)

get_distance.py


import json
import pandas as pd
import requests
import time


def progress_decolator(input_function):
    """Decolator to print * to show progress"""
    def return_function(*args, **kwargs):
        print("*", end="")
        result = input_function(*args, **kwargs)
        return result
    return return_function


def get_distance_API(lat1, lng1, lat2, lng2):
    """ Get distance between two points described with latitute and longitude.
    Details of the API can be found here: https://vldb.gsi.go.jp/sokuchi/surveycalc/api_help.html
    Validate the result using this web app : https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2stf.html
    Input : latitute and longitude of two points (float)
        eg) 35.6585769, 139.7454506, 35.710256, 139.8107946
    Output : distance of input two points with kilo meter unit (float)
        eg) 8.237
    """
    url = "http://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2st_calc.pl?latitude1={}&longitude1={}&latitude2={}&longitude2={}&ellipsoid=bessel&outputType=json".format(lat1,lng1,lat2,lng2)
    i_count = 0
    while i_count <= 10:
        result = requests.get(url)
        status_code = result.status_code
        if status_code == 200:
            break
        i_count += 1    
        time.sleep(2)
        print("retry : {}".format(i_count+1),end="")
        
    result_json = json.loads(result.text)
    distance = "0" + result_json["OutputData"]["geoLength"] 
    if distance == "0":
        print("error here")
        print(url)
        print(result)
        print(result_json)
    return round(float(distance)/1000, 3)

def get_distance_locally(lat_a, lon_a,lat_b, lon_b):
    """
    Credit : https://qiita.com/damyarou/items/9cb633e844c78307134a
    """
    ra=6378.140  # equatorial radius (km)
    rb=6356.755  # polar radius (km)
    F=(ra-rb)/ra # flattening of the earth
    rad_lat_a=np.radians(lat_a)
    rad_lon_a=np.radians(lon_a)
    rad_lat_b=np.radians(lat_b)
    rad_lon_b=np.radians(lon_b)
    pa=np.arctan(rb/ra*np.tan(rad_lat_a))
    pb=np.arctan(rb/ra*np.tan(rad_lat_b))
    xx=np.arccos(np.sin(pa)*np.sin(pb)+np.cos(pa)*np.cos(pb)*np.cos(rad_lon_a-rad_lon_b))
    c1=(np.sin(xx)-xx)*(np.sin(pa)+np.sin(pb))**2/np.cos(xx/2)**2
    c2=(np.sin(xx)+xx)*(np.sin(pa)-np.sin(pb))**2/np.sin(xx/2)**2
    dr=F/8*(c1-c2)
    rho=ra*(xx+dr)
    return rho

@progress_decolator
def get_distance(lat1, lng1, lat2, lng2, method=0):
    if method == 0:
        return_distance = get_distance_API(lat1, lng1, lat2, lng2)
    else: 
        return_distance = get_distance_locally(lat1, lng1, lat2, lng2)
    return return_distance 


def create_matrix(n_row, n_col):
    """Create matrix filled with nan in decided size
    
    Input : n_row(int), n_col(int)
    Output : dataframe
    """
    
    matrix = pd.DataFrame(index=range(n_row), columns=range(n_col))
    return matrix



# main here

df1 = pd.read_csv("PATH1.csv")
df2 = pd.read_csv("PATH2.csv")

matrix = create_matrix(len(df1), len(df2))

for i in range(len(df1)):
    for j in range(len(df2)):
        distance = get_distance(df1.loc[i,"latitude"], 
                                df1.loc[i,"longitude"], 
                                df2.loc[j, "latitude"], 
                                df2.loc[j, "longitude"],
                               method = 0)
        if distance == 0:
            # if distance equal 0, that is most probably wrong. check what is the problem.
            #Si la distance est de 0, il y a souvent un problème. Par conséquent, veuillez vérifier.
            print(df1[i])
            print(df2[j])
        matrix.iloc[i,j] = distance
        
matrix.to_csv("output.csv", encoding='utf_8_sig')

# if you want to decolate output with headings, run the followings
#Ci-dessous, l'ajout de l'en-tête. Veuillez l'exécuter arbitrairement.

col_expanded = pd.concat([df1[["name","address"]],matrix], axis = "columns")
df_head = pd.DataFrame([[""]*2,[""]*2],columns=["name","address"])
df_head = pd.concat([df_head , df2[["name","address"]]], ignore_index=True).T.reset_index(drop=True)
df_head.columns = col_expanded.columns
df_head.index = ["name", "address"]
df_expanded = pd.concat([df_head, col_expanded])
df_expanded.to_csv("output_with_header.csv", encoding='utf_8_sig')


À la fin / Clôture

Veuillez me faire savoir si vous avez des informations sur le changement d'emploi Hire me. https://www.linkedin.com/in/taigakubota/

Recommended Posts

Automatisation d'une recherche sur des informations géographiques telles que le réseau de magasins à l'aide de Python et de l'API Web
Développement et déploiement de l'API REST en Python à l'aide de Falcon Web Framework
Créer une carte Web en utilisant Python et GDAL
[Python3] Prenez une capture d'écran d'une page Web sur le serveur et recadrez-la davantage
Obtenez une liste des comptes GA, des propriétés et des vues sous forme de données verticales à l'aide de l'API
[python] [Gracenote Web API] Une petite personnalisation de pygn
Informations de raclage Web sur les programmes de rire et notification en ligne
Construire un environnement Python sur un Mac, jusqu'au point d'utiliser Jupyter Lab
Définir des informations telles que la longueur sur le bord de NetworkX
J'ai créé Chatbot en utilisant l'API LINE Messaging et Python
Créez un classement de jeu sur le cloud Alibaba en utilisant Python et Redis
Un peu plus sur les références ~ Prenant Python et Java comme exemples ~
Collectez des informations sur les produits et traitez les données à l'aide de l'API de recherche de produits Rakuten [Python]
[Python] J'ai écrit une API REST en utilisant AWS API Gateway et Lambda.
J'ai créé Chatbot en utilisant l'API LINE Messaging et Python (2) ~ Server ~
[Ruby on Rails] Affichage et épinglage de GoolgeMAP à l'aide de l'API Google
J'ai fait beaucoup de recherches sur la façon dont Python est exécuté
[MS Azure] Notification Slack des informations de compétition avec Azure Functions et l'API Kaggle
Essayez d'utiliser Spatia Lite, qui stocke des informations spatiales telles que des cartes dans SQLite
Hit une méthode d'une instance de classe avec l'API Web Python Bottle
Je souhaite créer une application Web en utilisant React et Python flask
Créez rapidement un environnement d'exécution d'application Web Python3.4 + Nginx + uWSGI + Flask en utilisant venv sur Ubuntu 14.04 LTS
Soudain, j'avais besoin de travailler sur un projet utilisant Python et Pyramid, donc une note sur la façon dont j'étudie
Un mémo contenant Python2.7 et Python3 dans CentOS
Carte des informations de location sur une carte avec python
Connectez beaucoup de Python ou et et
Voir les informations sur les fichiers et les dossiers sur python
Étude sur Tokyo Rent en utilisant Python (3-1 sur 3)
Automatisation égale de l'installation de Python et PyPI
[Python] Obtenez des informations produit telles que ASIN et JAN avec Amazon PA-API ver5.0
Laisser Python mesurer le score moyen d'une page à l'aide de l'API PageSpeed Insights
En étudiant JQuery et Python jusqu'à la publication d'un service Web sur GCP