<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Men of Letters（メン・オブ・レターズ） &#8211; 論理的思考/業務改善/プログラミング</title>
	<atom:link href="https://laboratory.kazuuu.net/feed/" rel="self" type="application/rss+xml" />
	<link>https://laboratory.kazuuu.net</link>
	<description></description>
	<lastBuildDate>Tue, 07 Jul 2026 02:13:12 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://laboratory.kazuuu.net/wp-content/uploads/2021/02/cropped-L-32x32.png</url>
	<title>Men of Letters（メン・オブ・レターズ） &#8211; 論理的思考/業務改善/プログラミング</title>
	<link>https://laboratory.kazuuu.net</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://laboratory.kazuuu.net/feed/"/>
	<item>
		<title>Building an Automated B2B Lead Generator &#038; Spatial Heatmap with SearchApi and Python</title>
		<link>https://laboratory.kazuuu.net/building-an-automated-b2b-lead-generator-spatial-heatmap-with-searchapi-and-python/</link>
					<comments>https://laboratory.kazuuu.net/building-an-automated-b2b-lead-generator-spatial-heatmap-with-searchapi-and-python/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Tue, 07 Jul 2026 02:09:26 +0000</pubDate>
				<category><![CDATA[Python【初歩から現場実務的なもの】]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17903</guid>

					<description><![CDATA[Public economic data and official directories are often plagued by lag and rigid structures. For businesses lo [&#8230;]]]></description>
										<content:encoded><![CDATA[<p data-path-to-node="4">Public economic data and official directories are often plagued by lag and rigid structures. For businesses looking for high-intent B2B sales leads, or data analysts seeking real-time local market indicators, having a &#8220;live&#8221; data pipeline is a massive competitive advantage.</p>
<p data-path-to-node="5">In this tutorial, we will build an end-to-end Python pipeline using <b data-path-to-node="5" data-index-in-node="68">SearchApi</b> (specifically the Google Maps and Google Place engines) to achieve two high-value outcomes simultaneously:</p>
<ol start="1" data-path-to-node="6">
<li>
<p data-path-to-node="6,0,0"><b data-path-to-node="6,0,0" data-index-in-node="0">Commercial Use Case:</b> Automatically generate a premium, corporate-styled Excel spreadsheet (<code data-path-to-node="6,0,0" data-index-in-node="91">.xlsx</code>) containing deeply enriched B2B sales leads (Names, Addresses, Phone Numbers, Websites, and Pricing Tiers).</p>
</li>
<li>
<p data-path-to-node="6,1,0"><b data-path-to-node="6,1,0" data-index-in-node="0">Analytical Use Case:</b> Automatically render a fully interactive HTML spatial map (<code data-path-to-node="6,1,0" data-index-in-node="80">folium</code>), dynamic and color-coded based on local price levels ($, $$, $$$).</p>
</li>
</ol>
<h2>Why SearchApi? Bypassing Infrastructure Hurdles</h2>
<p>Extracting high-quality, high-frequency location data directly from mapping platforms is notoriously difficult. Sophisticated anti-bot protections, aggressive IP rate-limiting, and sudden CAPTCHAs can easily break custom-built web scrapers, leading to high maintenance costs and incomplete datasets.</p>
<p>This is where <span class="hljs-strong">SearchApi</span> serves as the critical infrastructure for our project. By handling real-time proxy rotation, CAPTCHA solving, and data retrieval under the hood, it returns clean, structured JSON instantly. Instead of wasting dozens of hours battling infrastructure hurdles and managing headless browsers, this API-first approach allows us to focus 100% of our energy on the core logic of data interpretation, commercial structuring, and visual mapping.</p>
<h2 data-path-to-node="8">1. Architecture Overview: The Power of Multi-Engine Data Enrichment</h2>
<p data-path-to-node="9">Standard web scraping tools easily break due to Google&#8217;s robust anti-bot infrastructure. By treating <b data-path-to-node="9" data-index-in-node="101">SearchApi</b> as our critical infrastructure, we bypass proxy management and headless browser configurations entirely, allowing us to focus 100% on data structure and analysis.</p>
<p data-path-to-node="10">Our script utilizes a two-tier data enrichment pipeline:</p>
<ul data-path-to-node="11">
<li>
<p data-path-to-node="11,0,0"><b data-path-to-node="11,0,0" data-index-in-node="0">Tier 1 (<code data-path-to-node="11,0,0" data-index-in-node="8">google_maps</code>)</b>: Sweeps a targeted geographic coordinate and radius based on your industry query (e.g., &#8220;steakhouse&#8221;, &#8220;dentist&#8221;, &#8220;coffee shop&#8221;) to compile a comprehensive local business registry.</p>
</li>
<li>
<p data-path-to-node="11,1,0"><b data-path-to-node="11,1,0" data-index-in-node="0">Tier 2 (<code data-path-to-node="11,1,0" data-index-in-node="8">google_place</code>)</b>: Sequentially takes the unique identifiers (<code data-path-to-node="11,1,0" data-index-in-node="66">kgmid</code> or <code data-path-to-node="11,1,0" data-index-in-node="75">place_id</code>) from Tier 1 to fetch deep-layer operational metadata, such as exact pricing details and missing contact points.</p>
</li>
</ul>
<h2 data-path-to-node="13">2. Complete Python Script (<code data-path-to-node="13" data-index-in-node="27">sales_and_map_pipeline.py</code>)</h2>
<p data-path-to-node="14">This production-grade script features defensive type-checking and exponential backoff retry logic to handle unexpected API structures flawlessly without crashing.</p>
<pre>import requests
import time
import logging
import os
import math
from datetime import datetime
from collections import Counter
from typing import List, Dict, Tuple

import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.utils import get_column_letter

try:
    import folium
    from folium import FeatureGroup, LayerControl
    FOLIUM_AVAILABLE = True
except ImportError:
    FOLIUM_AVAILABLE = False

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", datefmt="%H:%M:%S")
logger = logging.getLogger(__name__)

# ============================================================
# ====================== CONFIGURATION =======================
# ============================================================

API_KEY = os.getenv("SEARCHAPI_KEY") or "YOUR_SEARCHAPI_KEY_HERE"

# === Search Settings ===
SEARCH_QUERY = "steakhouse"                    # Target industry (e.g. "coffee shop", "dentist", "sushi")
LOCATION = "@40.7128,-74.0060,14z"             # Coordinates + zoom level (e.g., New York City)
LANGUAGE = "en"                                # "en", "ja", "es", etc.
COUNTRY = "us"                                 # Country code

MAX_PAGES = 3
SEARCH_SLEEP = 1.8

# === Detail Enrichment (Price + Contact Info) ===
ENRICH_DETAILS = False                         # Set True to fetch deep price/contact details via google_place
DETAIL_TOP_N = 0                               # 0 = all results, or limit number to control costs

# === Output Files ===
TIMESTAMP = datetime.now().strftime('%Y%m%d_%H%M')
EXCEL_FILENAME = f"business_analysis_{TIMESTAMP}.xlsx"
CSV_FILENAME = f"business_analysis_{TIMESTAMP}.csv"
MAP_FILENAME = f"business_map_{TIMESTAMP}.html"

# ============================================================
# ====================== HELPER FUNCTIONS ====================
# ============================================================

def normalize_price_band(price_str: str) -&gt; str:
    if not price_str:
        return "Unknown"
    price_str = str(price_str).strip().lower()
    if "¥¥¥¥" in price_str or "$$$$" in price_str:
        return "Very Expensive"
    elif "¥¥¥" in price_str or "$$$" in price_str:
        return "Expensive"
    elif "¥¥" in price_str or "$$" in price_str:
        return "Moderate"
    elif "¥" in price_str or "$" in price_str:
        return "Inexpensive"
    return "Unknown"

def get_price_color(price_level: str) -&gt; str:
    colors = {
        "Inexpensive": "green",
        "Moderate": "blue",
        "Expensive": "orange",
        "Very Expensive": "red",
        "Unknown": "gray"
    }
    return colors.get(price_level, "gray")

def parse_gps(place: dict) -&gt; Tuple[float, float]:
    gps = place.get("gps_coordinates", {})
    if isinstance(gps, dict):
        try:
            return float(gps.get("latitude", 0)), float(gps.get("longitude", 0))
        except:
            pass
    return 0.0, 0.0

def calculate_popularity_score(rating: float, reviews: int) -&gt; float:
    if not rating or not reviews:
        return 0.0
    return round(rating * math.log(reviews + 1), 2)

def extract_base_info(place: dict) -&gt; dict:
    lat, lng = parse_gps(place)
    rating = float(place.get("rating", 0) or 0)
    reviews = int(place.get("reviews", 0) or 0)
    raw_price = place.get("price", "") or place.get("price_description", "")

    return {
        "Name": place.get("title", ""),
        "Address": place.get("address", ""),
        "Phone": place.get("phone", ""),
        "Website": place.get("website", ""),
        "Latitude": lat,
        "Longitude": lng,
        "Rating": rating,
        "Review Count": reviews,
        "Category": ", ".join(place.get("types", [])) if isinstance(place.get("types"), list) else place.get("type", ""),
        "Price Level": normalize_price_band(raw_price),
        "Raw Price": raw_price,
        "Business Status": place.get("open_state", ""),
        "Popularity Score": calculate_popularity_score(rating, reviews),
        "kgmid": place.get("kgmid", ""),
        "Place ID": place.get("place_id", ""),
        "Price Min": None,
        "Price Max": None,
        "Price Range Text": "",
        "Typical Spend": "",
        "Scraped At": datetime.now().isoformat()
    }

def get_place_details(kgmid: str = None, place_id: str = None) -&gt; dict:
    if not (kgmid or place_id):
        return {}

    identifier = kgmid or place_id
    param_name = "kgmid" if kgmid else "place_id"

    try:
        params = {
            "engine": "google_place",
            param_name: identifier,
            "hl": LANGUAGE,
            "gl": COUNTRY
        }
        data = requests.get(
            "https://www.searchapi.io/api/v1/search",
            params={"api_key": API_KEY, **params},
            timeout=25
        ).json()

        place = data.get("place_result") or data.get("place_results", {})
        if not isinstance(place, dict):
            return {}

        price_info = place.get("price", {})
        if isinstance(price_info, dict):
            price_min = price_info.get("min")
            price_max = price_info.get("max")
            price_text = price_info.get("text", "")
        else:
            price_min = price_max = None
            price_text = str(price_info) if price_info else ""

        return {
            "Phone": place.get("phone", ""),
            "Website": place.get("website", ""),
            "Price Min": price_min,
            "Price Max": price_max,
            "Price Range Text": price_text,
            "Typical Spend": place.get("people_typically_spend", "")
        }
    except Exception as e:
        logger.warning(f"Detail fetch error: {e}")
        return {}

def extract_and_enrich_stores(data: dict) -&gt; List[Dict]:
    stores = [extract_base_info(place) for place in data.get("local_results", []) if isinstance(place, dict)]

    if ENRICH_DETAILS and stores:
        sorted_stores = sorted(stores, key=lambda x: x.get("Popularity Score", 0), reverse=True)
        target_stores = sorted_stores[:DETAIL_TOP_N] if DETAIL_TOP_N &gt; 0 else stores

        for store in target_stores:
            if store.get("kgmid") or store.get("Place ID"):
                detail = get_place_details(store.get("kgmid"), store.get("Place ID"))
                if detail:
                    for key in ["Phone", "Website", "Price Min", "Price Max", "Price Range Text", "Typical Spend"]:
                        if detail.get(key):
                            store[key] = detail[key]
                time.sleep(DETAIL_SLEEP)

    return stores

# ================== ANALYSIS ==================
def analyze_businesses(stores: List[Dict]):
    if not stores:
        return

    print("\n" + "="*80)
    print("📊 Local Business Analysis Report")
    print("="*80)

    total = len(stores)
    price_counts = Counter(s.get("Price Level", "Unknown") for s in stores)

    print(f"Total Businesses Found: {total}")
    print("\n【Price Level Distribution】")
    for level in ["Inexpensive", "Moderate", "Expensive", "Very Expensive", "Unknown"]:
        count = price_counts.get(level, 0)
        if count &gt; 0:
            print(f"  {level:15} : {count:3} businesses ({count/total*100:5.1f}%)")

    has_phone = sum(1 for s in stores if s.get("Phone"))
    print(f"\nBusinesses with Phone Number: {has_phone}/{total}")
    print("="*80 + "\n")

# ================== EXPORT ==================
def save_to_excel(stores: List[Dict], filename: str):
    if not stores:
        return

    df = pd.DataFrame(stores)
    columns_order = [
        "Name", "Address", "Phone", "Website", "Rating", "Review Count",
        "Price Level", "Price Min", "Price Max", "Popularity Score",
        "Latitude", "Longitude", "Category", "Business Status", "Scraped At"
    ]
    df = df[[col for col in columns_order if col in df.columns]]

    wb = Workbook()
    ws = wb.active
    ws.title = "Business Data"

    for r_idx, row in enumerate(dataframe_to_rows(df, index=False, header=True), 1):
        for c_idx, value in enumerate(row, 1):
            ws.cell(row=r_idx, column=c_idx, value=value)

    # Corporate Header Styling (Navy / White)
    header_fill = PatternFill(start_color="1F4E79", end_color="1F4E79", fill_type="solid")
    header_font = Font(bold=True, color="FFFFFF", size=11)
    for cell in ws[1]:
        cell.fill = header_fill
        cell.font = header_font
        cell.alignment = Alignment(horizontal='center', vertical='center')

    # Auto-fit Column Widths
    for col_idx in range(1, ws.max_column + 1):
        ws.column_dimensions[get_column_letter(col_idx)].width = 18

    ws.freeze_panes = 'A2'
    wb.save(filename)
    logger.info(f"✅ Excel report saved: {filename}")

def save_to_csv(stores: List[Dict], filename: str):
    if stores:
        pd.DataFrame(stores).to_csv(filename, index=False, encoding="utf-8-sig")
        logger.info(f"✅ CSV saved: {filename}")

# ================== INTERACTIVE MAP ==================
def generate_map(stores: List[Dict], filename: str):
    if not FOLIUM_AVAILABLE or not stores:
        return

    valid_coords = [(s["Latitude"], s["Longitude"]) for s in stores if s.get("Latitude") and s.get("Longitude")]
    if valid_coords:
        center_lat = sum(lat for lat, _ in valid_coords) / len(valid_coords)
        center_lng = sum(lng for _, lng in valid_coords) / len(valid_coords)
        center = [center_lat, center_lng]
    else:
        center = [40.7128, -74.0060]

    m = folium.Map(location=center, zoom_start=13, tiles="cartodbpositron")
    price_layer = FeatureGroup(name="By Price Level", show=True)

    for store in stores:
        if not store.get("Latitude") or not store.get("Longitude"):
            continue

        color = get_price_color(store.get("Price Level", "Unknown"))
        popup_html = f"""
        <b>{store['Name']}</b>
        Phone: {store.get('Phone', 'N/A')}
        <a href="{store.get('Website', '#')}" target="_blank">Website</a>
        Price Level: <b>{store.get('Price Level')}</b>
        """

        folium.Marker(
            location=[store["Latitude"], store["Longitude"]],
            popup=folium.Popup(popup_html, max_width=300),
            tooltip=store['Name'],
            icon=folium.Icon(color=color, icon="info-sign")
        ).add_to(price_layer)

    price_layer.add_to(m)
    LayerControl(collapsed=False).add_to(m)
    m.save(filename)
    logger.info(f"🗺️ Interactive map saved: {filename}")

# ================== MAIN ==================
def main():
    target_params = {
        "engine": "google_maps",
        "q": SEARCH_QUERY,
        "ll": LOCATION,
        "hl": LANGUAGE,
        "gl": COUNTRY
    }

    logger.info(f"🚀 Starting analysis → Query: '{SEARCH_QUERY}' | Location: {LOCATION}")

    all_stores = []
    for page in range(1, MAX_PAGES + 1):
        target_params["page"] = page
        logger.info(f"📄 Fetching page {page}...")
        try:
            response = requests.get(
                "https://www.searchapi.io/api/v1/search",
                params={"api_key": API_KEY, **target_params},
                timeout=30
            )
            data = response.json()
            all_stores.extend(extract_and_enrich_stores(data))

            if page &lt; MAX_PAGES:
                time.sleep(SEARCH_SLEEP)
        except Exception as e:
            logger.error(f"Error on page {page}: {e}")
            break

    analyze_businesses(all_stores)
    save_to_excel(all_stores, EXCEL_FILENAME)
    save_to_csv(all_stores, CSV_FILENAME)

    if FOLIUM_AVAILABLE:
        generate_map(all_stores, MAP_FILENAME)

    logger.info(f"🎉 Analysis complete! Processed {len(all_stores)} businesses.")

if __name__ == "__main__":
    main()
</pre>
<h2 data-path-to-node="17">3. Core Highlights of the Script</h2>
<h3 data-path-to-node="18">3.1. Instant Premium B2B Lead List (Commercial Value)</h3>
<p data-path-to-node="19">Instead of outputting an unstyled, raw text file, the script integrates <code data-path-to-node="19" data-index-in-node="72">openpyxl</code> to build an execution-ready corporate directory.</p>
<ul data-path-to-node="20">
<li>
<p data-path-to-node="20,0,0"><b data-path-to-node="20,0,0" data-index-in-node="0">Freeze Panes:</b> Keeps the header visible while scrolling through hundreds of entries.</p>
</li>
<li>
<p data-path-to-node="20,1,0"><b data-path-to-node="20,1,0" data-index-in-node="0">Auto-Fit Layout:</b> Calculates optimal column widths dynamically so strings like addresses and domain names don&#8217;t get clipped.</p>
</li>
<li>
<p data-path-to-node="20,2,0"><b data-path-to-node="20,2,0" data-index-in-node="0">Rich Fields:</b> Extracts telephone contacts and websites directly, providing an instant directory for sales teams or outreach automation tools.</p>
</li>
</ul>
<h3 data-path-to-node="21">3.2. Macroeconomic Spatial Profiling (Analytical Value)</h3>
<p data-path-to-node="22">By taking advantage of <code data-path-to-node="22" data-index-in-node="23">folium</code> (a Python wrapper for the powerful Leaflet.js library), the data pipeline parses incoming JSON GPS coordinates on the fly.</p>
<ul data-path-to-node="23">
<li>
<p data-path-to-node="23,0,0">Marker icons are evaluated dynamically based on parsed market values.</p>
</li>
<li>
<p data-path-to-node="23,1,0">It generates an standalone interactive HTML file containing a map overlay, grouping targets into distinct pricing sub-layers (Inexpensive, Moderate, Expensive, Very Expensive). This visually highlights local inflation density, high-end commercial hubs, or market gaps in target metropolitan areas.</p>
</li>
</ul>
<h2 data-path-to-node="25">4. Conclusion &amp; Next Steps</h2>
<p data-path-to-node="26">By combining SearchApi&#8217;s robust mapping extraction capabilities with smart Python styling and geographic rendering, we transformed raw location records into highly structured commercial intelligence.</p>
<p data-path-to-node="27">Whether you are seeking to automate cold outreach lead generation or map out the socio-economic topography of a city, this script serves as your robust foundation. In a future post, we will explore turning this static mapping pipeline into a dynamic, real-time web application dashboard.</p>
<p data-path-to-node="28"><i data-path-to-node="28" data-index-in-node="0">What industry or region are you planning to map out first? Let us know in the comments below!</i></p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/building-an-automated-b2b-lead-generator-spatial-heatmap-with-searchapi-and-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Building a Real-time Economic Indicator (REI) Tracker with SearchApi and Python</title>
		<link>https://laboratory.kazuuu.net/building-a-real-time-economic-indicator-rei-tracker-with-searchapi-and-python/</link>
					<comments>https://laboratory.kazuuu.net/building-a-real-time-economic-indicator-rei-tracker-with-searchapi-and-python/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Thu, 21 May 2026 02:26:37 +0000</pubDate>
				<category><![CDATA[Python【初歩から現場実務的なもの】]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17898</guid>

					<description><![CDATA[1. Introduction: The Problem of Latency in Official Statistics Official economic metrics, such as the Consumer [&#8230;]]]></description>
										<content:encoded><![CDATA[<h4 data-path-to-node="23">1. Introduction: The Problem of Latency in Official Statistics</h4>
<p id="p-rc_ef4287599fe58577-35" data-path-to-node="24"><span data-path-to-node="24,1"><span class="citation-23">Official economic metrics, such as the Consumer Price Index (CPI), are foundational to understanding macro trends</span></span><span data-path-to-node="24,3">. </span><span data-path-to-node="24,5"><span class="citation-22">However, they suffer from a structural defect: </span><b data-path-to-node="24,5" data-index-in-node="47"><span class="citation-22">latency</span></b></span><span data-path-to-node="24,7">. </span><span data-path-to-node="24,9"><span class="citation-21">By the time government statistics are officially released, the market has already moved on</span></span><span data-path-to-node="24,11">.</span></p>
<p id="p-rc_ef4287599fe58577-36" data-path-to-node="25"><span data-path-to-node="25,1"><span class="citation-20">For developers and analysts, bridging this informational gap requires a proactive engineering approach to data collection</span></span><span data-path-to-node="25,3">. </span><span data-path-to-node="25,5"><span class="citation-19">This project aims to build a </span><b data-path-to-node="25,5" data-index-in-node="29"><span class="citation-19">Real-time Economic Indicator (REI) Tracker</span></b></span><span data-path-to-node="25,7">. </span><span data-path-to-node="25,9"><span class="citation-18">By monitoring the digital shelf prices of essential goods in a specific metropolitan area (Osaka, Japan), we can identify inflationary or deflationary trends weeks before they appear in official reports</span></span><span data-path-to-node="25,11">.</span></p>
<h4 data-path-to-node="26">2. Bypassing Infrastructure Hurdles with SearchApi</h4>
<p id="p-rc_ef4287599fe58577-37" data-path-to-node="27"><span data-path-to-node="27,1"><span class="citation-17">Extracting high-quality, high-frequency data from search engines and shopping platforms is notoriously difficult due to sophisticated anti-bot protections, IP blocks, and CAPTCHAs</span></span><span data-path-to-node="27,3">.</span></p>
<p id="p-rc_ef4287599fe58577-38" data-path-to-node="29">SearchApi serves as the critical infrastructure for this project. By handling real-time data retrieval and returning it as clean JSON, it allows us to bypass issues we would otherwise face if we were to try to scrape data ourselves and focus entirely on the logic of data interpretation.</p>
<h4 data-path-to-node="30">3. Complete Source Code</h4>
<p data-path-to-node="31">Below is the robust Python implementation that covers everything from data extraction via SearchApi to data persistence in CSV format using Pandas, featuring duplication prevention for same-day runs.</p>
<pre>import requests
import statistics
import pandas as pd
from datetime import datetime, date
import os
import re
import logging
from pathlib import Path
from dataclasses import dataclass
from typing import List, Dict, Optional
from dotenv import load_dotenv

# ====================== setting ======================
load_dotenv()

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s | %(levelname)s | %(message)s',
    datefmt='%H:%M:%S'
)
logger = logging.getLogger(__name__)

API_KEY = os.getenv("SEARCHAPI_API_KEY")
if not API_KEY:
    raise ValueError("SEARCHAPI_API_KEY is not set in the .env file!")

@dataclass
class Config:
    target_items: List[str] = None
    location: str = "Osaka, Osaka, Japan"
    gl: str = "jp"
    hl: str = "ja"
    num_results: int = 20
    min_samples: int = 3

# Tracked products
config = Config(
    target_items=[
        "Egg 10-pack",
        "Rice 5kg",
        "Tissue paper 5-pack",
        "Gasoline price",
        "iPhone 15 128GB",
    ]
)

class EconomicIndicatorTracker:
    def __init__(self, api_key: str, config: Config):
        self.api_key = api_key
        self.config = config
        self.endpoint = "https://www.searchapi.io/api/v1/search"
        self.session = requests.Session()

    @staticmethod
    def parse_price(price_str: str) -&gt; Optional[int]:
        """Securely convert price strings to numbers"""
        if not price_str:
            return None
        cleaned = str(price_str).replace('円', '').replace('¥', '').replace(' ', '')
        cleaned = re.sub(r'[^\d.,]', '', cleaned)
        cleaned = cleaned.replace(',', '')
        try:
            return int(float(cleaned))
        except ValueError:
            return None

    def get_market_price(self, query: str) -&gt; Optional[Dict]:
        """Price data is retrieved from Google Shopping"""
        params = {
            "engine": "google_shopping",
            "q": query,
            "location": self.config.location,
            "api_key": self.api_key,
            "gl": self.config.gl,
            "hl": self.config.hl,
            "num": self.config.num_results,
        }

        try:
            response = self.session.get(self.endpoint, params=params, timeout=20)
            response.raise_for_status()
            data = response.json()

            prices = []
            for item in data.get("shopping_results", []):
                price_str = item.get("price") or item.get("extracted_price")
                if price_str:
                    parsed = self.parse_price(price_str)
                    if parsed and parsed &gt; 0:
                        prices.append(parsed)

            if len(prices) &lt; self.config.min_samples:
                logger.warning(f"There are too few valid samples for {query} ({len(prices)} items).")
                return None

            return {
                "item": query,
                "date": date.today().isoformat(),
                "timestamp": datetime.now().isoformat(),
                "median_price": round(statistics.median(prices)),
                "sample_count": len(prices),
                "min_price": min(prices),
                "max_price": max(prices)
            }
        except Exception as e:
            logger.error(f"Data acquisition error {query}: {e}")
        return None

def main():
    tracker = EconomicIndicatorTracker(API_KEY, config)
    results = []

    print(f"--- Real-world economic survey begins in the Osaka area ({date.today().isoformat()}) ---")
    
    for item in config.target_items:
        logger.info(f"Fetching: {item}...")
        stats = tracker.get_market_price(item)
        if stats:
            results.append(stats)
            logger.info(f"   → median: ¥{stats['median_price']:,} ({stats['sample_count']} 件)")

    if results:
        df_new = pd.DataFrame(results)
        csv_file = f"economic_indicator_{datetime.now().strftime('%Y%m')}.csv"
        
        # CSV persistence logic (preventing duplicate entries for the same day)
        if Path(csv_file).exists():
            df_existing = pd.read_csv(csv_file)
            df_existing = df_existing[df_existing['date'] != date.today().isoformat()]
            df_combined = pd.concat([df_existing, df_new], ignore_index=True)
        else:
            df_combined = df_new

        df_combined.to_csv(csv_file, index=False)
        logger.info(f"💾 Saved to CSV: {csv_file}")
        
        print("\n" + "="*50)
        print("### Market Price Summary ###")
        print(df_new[['item', 'median_price', 'sample_count']].to_string(index=False))
        print("="*50)
    else:
        logger.error("No data was collected.")

if __name__ == "__main__":
    main()</pre>
<h4 data-path-to-node="33">4. Analytical Methodology</h4>
<ul data-path-to-node="34">
<li>
<p id="p-rc_ef4287599fe58577-39" data-path-to-node="34,0,1"><span data-path-to-node="34,0,1,0"><b data-path-to-node="34,0,1,0" data-index-in-node="0"><span class="citation-14">Median Pricing:</span></b><span class="citation-14"> By prioritizing the Median over the Mean, we effectively eliminate the noise of extreme outliers (such as steep discounts, used items, or shipping entry errors) to find the true &#8220;market middle&#8221;</span></span><span data-path-to-node="34,0,1,2">.</span></p>
</li>
<li>
<p id="p-rc_ef4287599fe58577-40" data-path-to-node="34,1,1"><span data-path-to-node="34,1,1,0"><b data-path-to-node="34,1,1,0" data-index-in-node="0"><span class="citation-13">Localized Context:</span></b><span class="citation-13"> Setting the geo-location specifically to Osaka allows the script to capture regional supply chain shifts and local logistics impacts</span></span><span data-path-to-node="34,1,1,2">.</span></p>
</li>
<li>
<p id="p-rc_ef4287599fe58577-41" data-path-to-node="34,2,1"><span data-path-to-node="34,2,1,0"><b data-path-to-node="34,2,1,0" data-index-in-node="0"><span class="citation-12">Data Persistence:</span></b><span class="citation-12"> Automated monthly CSV updates generate a clean, reliable historical baseline for robust Month-over-Month (MoM) and Year-over-Year (YoY) economic analysis</span></span><span data-path-to-node="34,2,1,2">.</span></p>
</li>
</ul>
<h4 data-path-to-node="36">5. Open Source Repository &amp; Quick Start</h4>
<p data-path-to-node="37">The complete project files and deployment guide are available on GitHub.</p>
<ol start="1" data-path-to-node="38">
<li>
<p data-path-to-node="38,0,0"><b data-path-to-node="38,0,0" data-index-in-node="0">Clone &amp; Install</b>: Clone the repository and run <code data-path-to-node="38,0,0" data-index-in-node="46">pip install -r requirements.txt</code>.</p>
</li>
<li>
<p data-path-to-node="38,1,0"><b data-path-to-node="38,1,0" data-index-in-node="0">Get SearchApi Key</b>: Sign up at <a rel="noopener" class="ng-star-inserted" href="https://www.searchapi.io/" target="_blank" data-hveid="0" data-ved="0CAAQ_4QMahgKEwj2_snVnMmUAxUAAAAAHQAAAAAQ-wI">SearchApi.io</a> and copy your API key from the developer dashboard.</p>
</li>
<li>
<p data-path-to-node="38,2,0"><b data-path-to-node="38,2,0" data-index-in-node="0">Environment Setup</b>: Create a <code data-path-to-node="38,2,0" data-index-in-node="28">.env</code> file in the root folder and add your key: <code data-path-to-node="38,2,0" data-index-in-node="75">SEARCHAPI_API_KEY=your_api_key_here</code>.</p>
</li>
<li>
<p data-path-to-node="38,3,0"><b data-path-to-node="38,3,0" data-index-in-node="0">Run</b>: Execute <code data-path-to-node="38,3,0" data-index-in-node="13">python rei_tracker.py</code> to start collecting real-time market insights and generating your localized CSV datasets.</p>
</li>
</ol>
<p data-path-to-node="36">👉 <a href="https://github.com/kobayashikazu/rei-tracker-osaka">https://github.com/kobayashikazu/rei-tracker-osaka</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/building-a-real-time-economic-indicator-rei-tracker-with-searchapi-and-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>自由落下とpythonプログラム</title>
		<link>https://laboratory.kazuuu.net/free-fall-and-python-programs/</link>
					<comments>https://laboratory.kazuuu.net/free-fall-and-python-programs/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Sun, 18 Aug 2024 19:58:40 +0000</pubDate>
				<category><![CDATA[Python（遊び）]]></category>
		<category><![CDATA[数学]]></category>
		<category><![CDATA[物理学]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17679</guid>

					<description><![CDATA[自由落下に関するpythonプログラムを作ってみます。 なお、初速度 v0 が 0 m/s で、地上から自由落下する物体が 10 秒後にどのくらいの速度に達するかを計算し、結果を表示するPythonプログラムを作ります。 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>自由落下に関するpythonプログラムを作ってみます。</p>
<p>なお、初速度 v0 が 0 m/s で、地上から自由落下する物体が 10 秒後にどのくらいの速度に達するかを計算し、結果を表示するPythonプログラムを作ります。</p>
<h2>■今回の環境（Python）</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png"><img decoding="async" class="alignnone size-medium wp-image-17673" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png" alt="" width="300" height="131" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-768x336.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png 865w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(Google Colab)を使用。）</p>
<h2>■結果を表示するPythonプログラム</h2>
<h3>■コード</h3>
<pre># 重力加速度 (m/s²)
g = 9.81

# 初速度 (m/s)
v0 = 0

# 時間 (秒)
t = 10

# 速度を計算
v = v0 + g * t

# 結果を表示
print("10 秒後の速度は {:.2f} m/s です。".format(v))</pre>
<h2>■検証、確認</h2>
<p>作成したコードは、Google Colaboratoryの新しいノートブック上のセルにコードを記述します。その後「セルを実行」ボタンをクリックします。</p>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-02-132014.png"><img decoding="async" class="alignnone wp-image-17680 size-medium" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-02-132014-300x144.png" alt="" width="300" height="144" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-02-132014-300x144.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-02-132014-1024x493.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-02-132014-768x370.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-02-132014.png 1222w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>先に計算した結果を書くと「98.10 m/s」となります。クリックすると、Google Colaboratory上で処理された結果を確認すると「10 秒後の速度は 98.10 m/s です。」と出力させることができました。</p>
<h2>■補足</h2>
<h3>※速度の時間変化をアニメーションとして描画するためのコード</h3>
<p>import matplotlib.pyplot as plt</p>
<pre>import numpy as np
from matplotlib.animation import FuncAnimation

# 重力加速度 (m/s²)
g = 9.81

# 初速度 (m/s)
v0 = 0

# 時間 (秒)
t = 10

# 時間の配列を作成（0からtまで0.1秒刻み）
time = np.arange(0, t, 0.1)

# 速度の配列を計算
velocity = v0 + g * time

# グラフの初期設定
fig, ax = plt.subplots()
ax.set_xlim(0, t)
ax.set_ylim(0, max(velocity) + 1)
line, = ax.plot([], [], lw=2)

# アニメーションの初期化
def init():
    line.set_data([], [])
    return line,

# アニメーションのフレーム更新
def update(frame):
    x_data = time[:frame]
    y_data = velocity[:frame]
    line.set_data(x_data, y_data)
    return line,

# アニメーションの作成
ani = FuncAnimation(fig, update, frames=len(time), init_func=init, blit=True)

# アニメーションの表示
plt.xlabel('Time (s)')
plt.ylabel('Velocity (m/s)')
plt.title('Velocity vs. Time')
plt.show()</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/free-fall-and-python-programs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>matplotlibを用いて数学を使って図形を描く</title>
		<link>https://laboratory.kazuuu.net/drawing-shapes-using-mathematics-with-matplotlib/</link>
					<comments>https://laboratory.kazuuu.net/drawing-shapes-using-mathematics-with-matplotlib/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Tue, 13 Aug 2024 23:03:22 +0000</pubDate>
				<category><![CDATA[Python【初歩から現場実務的なもの】]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17705</guid>

					<description><![CDATA[matplotlibを用いて数学を使って図形を描いてみます。 ■今回の環境（Python） 今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(Google Colab [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>matplotlibを用いて数学を使って図形を描いてみます。</p>
<h2>■今回の環境（Python）</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png"><img decoding="async" class="alignnone size-medium wp-image-17673" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png" alt="" width="300" height="131" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-768x336.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png 865w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(Google Colab)を使用。）</p>
<h2>■結果を表示するPythonプログラム</h2>
<h3>■コード</h3>
<pre>import matplotlib.pyplot as plt
import numpy as np

# 円の中心座標
center = (0, 0)

# 円の半径
radius = 2

# 角度の範囲を指定（0から360度まで）
theta = np.linspace(0, 2*np.pi, 100)

# 円の座標を計算
x = center[0] + radius * np.cos(theta)
y = center[1] + radius * np.sin(theta)

# プロット
plt.plot(x, y)
plt.title('円の描画')
plt.xlabel('X軸')
plt.ylabel('Y軸')
plt.grid(True)
plt.show()
</pre>
<p>円の中心座標と半径を指定し、それを用いて円の座標を計算します。最後に、matplotlibのplot関数を使用して円をプロットし、show関数で表示します。</p>
<h2>■検証、確認</h2>
<p>作成したコードは、Google Colaboratoryの新しいノートブック上のセルにコードを記述します。その後「セルを実行」ボタンをクリックします。</p>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-09-144238.png"><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-17706" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-09-144238-300x194.png" alt="" width="300" height="194" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-09-144238-300x194.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-09-144238-1024x664.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-09-144238-768x498.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-09-144238.png 1159w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>クリックすると、matplotlibを用いて数学を使った図形を出力させることができました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/drawing-shapes-using-mathematics-with-matplotlib/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>斜めに投げられた物体とpythonプログラム</title>
		<link>https://laboratory.kazuuu.net/object-thrown-at-an-angle-and-python-program/</link>
					<comments>https://laboratory.kazuuu.net/object-thrown-at-an-angle-and-python-program/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Fri, 09 Aug 2024 19:13:18 +0000</pubDate>
				<category><![CDATA[Python（遊び）]]></category>
		<category><![CDATA[数学]]></category>
		<category><![CDATA[物理学]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17683</guid>

					<description><![CDATA[斜めに投げられた物体に関するpythonプログラムを作ってみます。 物体が斜めに投げられる場合、水平方向と鉛直方向の速度が影響します。水平方向の速度を Vx ​ 、鉛直方向の速度を Vy ​ とし、初速度 V0 ​ の物 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>斜めに投げられた物体に関するpythonプログラムを作ってみます。</p>
<p>物体が斜めに投げられる場合、水平方向と鉛直方向の速度が影響します。水平方向の速度を Vx ​ 、鉛直方向の速度を Vy ​ とし、初速度 V0 ​ の物体が角度 θ で斜めに投げられるとします。以下の式を使用して、物体の位置を時間と共に計算します。</p>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-141738.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-17684" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-141738.png" alt="" width="394" height="115" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-141738.png 394w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-141738-300x88.png 300w" sizes="(max-width: 394px) 100vw, 394px" /></a></p>
<p>ここで、x は水平方向の位置（メートル）、 y は鉛直方向の位置（メートル）、 t は時間（秒）です。</p>
<h2>■今回の環境（Python）</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png"><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-17673" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png" alt="" width="300" height="131" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-768x336.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png 865w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(Google Colab)を使用。）</p>
<h2>■斜めに投げられた物体に関するpythonプログラム</h2>
<p>今回は初速度 <span class="math math-inline"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span><span class="vlist-s">​</span></span></span></span></span><span class="mrel">=</span></span><span class="base"><span class="mord">20</span></span></span></span></span> m/s で、角度 <span class="math math-inline"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="mord mathnormal">θ</span><span class="mrel">=</span></span><span class="base"><span class="mord">3</span><span class="mord">0<span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∘</span></span></span></span></span></span></span></span></span></span></span> で斜めに投げられた物体の高度を時間と共に計算し、0 になる時間を求めるプログラムを作ってみます。プログラムを実行後、物体が地上に戻る時間を計算します。</p>
<h3>■コード</h3>
<pre>import math

# 初速度 (m/s)
v0 = 20

# 投げる角度 (度)
theta = 30

# 重力加速度 (m/s²)
g = 9.81

# 角度をラジアンに変換
theta = math.radians(theta)

# 初速度を水平方向と鉛直方向の速度に分解
vx = v0 * math.cos(theta)
vy = v0 * math.sin(theta)

# 物体が地上に戻る時間を計算
t = (2 * vy) / g

# 結果を表示
print("物体が地上に戻る時間は {:.2f} 秒です。".format(t))</pre>
<h3>■検証、確認</h3>
<p>作成したコードは、Google Colaboratoryの新しいノートブック上のセルにコードを記述します。その後「セルを実行」ボタンをクリックします。</p>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-143003.png"><img loading="lazy" decoding="async" class="alignnone wp-image-17688 size-medium" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-143003-300x202.png" alt="" width="300" height="202" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-143003-300x202.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-143003-1024x688.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-143003-768x516.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-06-143003.png 1027w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>先に答えを書くと「2.04 秒」となります。クリック後、Google Colaboratory上で処理された計算結果を確認すると「物体が地上に戻る時間は 2.04 秒です。」と出力させることができました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/object-thrown-at-an-angle-and-python-program/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Pythonを使用した簡単な代数の問題を解く</title>
		<link>https://laboratory.kazuuu.net/solve-simple-algebra-problems-using-python/</link>
					<comments>https://laboratory.kazuuu.net/solve-simple-algebra-problems-using-python/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Fri, 09 Aug 2024 04:32:40 +0000</pubDate>
				<category><![CDATA[Python（遊び）]]></category>
		<category><![CDATA[数学]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17676</guid>

					<description><![CDATA[Pythonを使用した簡単な代数の問題を解くことについて解説します。 今回は代数方程式を解くためにSymPyを使用します。Google ColaboratoryではSympyがすでにインストールされた状態となっています。 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Pythonを使用した簡単な代数の問題を解くことについて解説します。</p>
<p>今回は代数方程式を解くためにSymPyを使用します。Google ColaboratoryではSympyがすでにインストールされた状態となっています。</p>
<h2>■今回の環境（Python）</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png"><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-17673" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png" alt="" width="300" height="131" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-768x336.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png 865w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(Google Colab)を使用。）</p>
<h2>■簡単な代数の問題を解く</h2>
<p>以下の代数方程式を解く</p>
<pre>3x−5=10</pre>
<h3>■コード</h3>
<pre>import sympy as sp

# 未知数を定義
x = sp.symbols('x')

# 代数方程式を定義
equation = 3*x - 5 - 10

# 方程式を解く
solution = sp.solve(equation, x)

print("方程式の解は x =", solution[0])</pre>
<h2>■検証、確認</h2>
<p>作成したコードは、Google Colaboratoryの新しいノートブック上のセルにコードを記述します。その後「セルを実行」ボタンをクリックします。</p>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-01-150725.png"><img loading="lazy" decoding="async" class="alignnone wp-image-17677 size-medium" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-01-150725-300x141.png" alt="" width="300" height="141" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-01-150725-300x141.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-01-150725-1024x483.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-01-150725-768x362.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/11/スクリーンショット-2023-11-01-150725.png 1249w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>クリックすると、代数方程式の答えは「x=5」となりますので、Google Colaboratory上で処理された結果を確認すると「方程式の解は x = 5」と出力されていますので、代数の問題を解くことができました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/solve-simple-algebra-problems-using-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>フィボナッチ数列を使って三角形を出力するPythonコード</title>
		<link>https://laboratory.kazuuu.net/python-code-to-output-a-triangle-using-the-fibonacci-sequence/</link>
					<comments>https://laboratory.kazuuu.net/python-code-to-output-a-triangle-using-the-fibonacci-sequence/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Wed, 07 Aug 2024 19:30:52 +0000</pubDate>
				<category><![CDATA[Python（遊び）]]></category>
		<category><![CDATA[数学]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17672</guid>

					<description><![CDATA[今回は、フィボナッチ数列を使って三角形を出力するPythonコードを作ってみます。 ■今回の環境（Python） 今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(G [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>今回は、フィボナッチ数列を使って三角形を出力するPythonコードを作ってみます。</p>
<h2>■今回の環境（Python）</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png"><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-17673" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png" alt="" width="300" height="131" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-300x131.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813-768x336.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-134813.png 865w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonは、バージョン3.10.12を用いる。（なお、Google Colaboratory(Google Colab)を使用。）</p>
<h2>■フィボナッチ数列を使って三角形を出力する</h2>
<p>では、フィボナッチ数列を使って三角形を出力するPythonコードを書いていきます。</p>
<pre>def generate_fibonacci_triangle(rows):
    fibonacci_numbers = [1, 1]
    fibonacci_triangle = [[1], [1, 1]]

    for n in range(2, rows):
        fibonacci_n = fibonacci_numbers[n - 1] + fibonacci_numbers[n - 2]
        fibonacci_numbers.append(fibonacci_n)

        row = [1]
        for i in range(1, n):
            row.append(fibonacci_numbers[i])
        fibonacci_triangle.append(row)

    return fibonacci_triangle

def print_fibonacci_triangle(triangle):
    max_width = len(' '.join(map(str, triangle[-1])))

    for row in triangle:
        row_str = ' '.join(map(str, row))
        print(row_str.center(max_width))

if __name__ == "__main__":
    num_rows = 15  # 任意の行数を指定できます
    triangle = generate_fibonacci_triangle(num_rows)
    print_fibonacci_triangle(triangle)</pre>
<p>このコードでは、指定した行数（num_rows）のフィボナッチ数列の三角形を生成し、それを表示します。print_fibonacci_triangle関数は、各行の要素を適切に中央揃えして表示します。必要に応じて、num_rowsを調整して三角形の高さを変更できます。</p>
<h2>■検証、確認</h2>
<p>作成したコードは、Google Colaboratoryの新しいノートブック上のセルにコードを記述します。その後「セルを実行」ボタンをクリックします。</p>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-135426.png"><img loading="lazy" decoding="async" class="alignnone wp-image-17674 size-medium" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-135426-300x200.png" alt="" width="300" height="200" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-135426-300x200.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-135426-1024x683.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-135426-768x512.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/10/スクリーンショット-2023-10-30-135426.png 1129w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>クリックすると、セル上のコードが読み込まれ処理が実行となり、出力が表示されます。出力結果を確認すると、フィボナッチ数列を使って三角形を出力することができました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/python-code-to-output-a-triangle-using-the-fibonacci-sequence/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Python】文字列編集の距離と類似性を計算する「python-Levenshtein」のインストール</title>
		<link>https://laboratory.kazuuu.net/python-installation-of-python-levenshtein-to-calculate-distance-and-similarity-of-string-edits/</link>
					<comments>https://laboratory.kazuuu.net/python-installation-of-python-levenshtein-to-calculate-distance-and-similarity-of-string-edits/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Wed, 07 Aug 2024 04:45:51 +0000</pubDate>
				<category><![CDATA[Python【初歩から現場実務的なもの】]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17584</guid>

					<description><![CDATA[文字列編集の距離と類似性を計算する「python-Levenshtein」のインストールについて解説しています。 「python-Levenshtein（https://github.com/maxbachmann/py [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>文字列編集の距離と類似性を計算する「python-Levenshtein」のインストールについて解説しています。</p>
<p>「python-Levenshtein（<a href="https://github.com/maxbachmann/python-Levenshtein">https://github.com/maxbachmann/python-Levenshtein</a>）」は、レーベンシュタイン距離と文字列の類似性を高速に計算する関数が含まれたPythonライブラリです。</p>
<h2>■Python</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334.png"><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-16692" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-300x139.png" alt="" width="300" height="139" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-300x139.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-1024x475.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-768x356.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334.png 1250w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonのバージョンは、「3.10.9」を使用しています。（Windows11）（pythonランチャーでの確認）</p>
<h2>■python-Levenshteinをインストールする</h2>
<p>python-Levenshteinをインストールを行いますが、今回はpipを経由してインストールを行うので、まずWindowsのコマンドプロンプトを起動します。</p>
<pre>pip install python-Levenshtein</pre>
<p>起動後、上記のコマンドを入力し、Enterキーを押します。</p>
<p>なお、今回は、pythonランチャーを使用しており、Python Version 3.10.9にインストールを行うために、バージョンの切り替えを行います。</p>
<pre>py -3.10 -m pip install python-Levenshtein</pre>
<p>切り替えるために、上記のコマンドを入力し、Enterキーを押します。</p>
<pre>Defaulting to user installation because normal site-packages is not writeable
Collecting python-Levenshtein
  Using cached python_Levenshtein-0.22.0-py3-none-any.whl (9.4 kB)
Collecting Levenshtein==0.22.0
  Using cached Levenshtein-0.22.0-cp310-cp310-win_amd64.whl (100 kB)
Collecting rapidfuzz&lt;4.0.0,&gt;=2.3.0
  Using cached rapidfuzz-3.3.1-cp310-cp310-win_amd64.whl (1.8 MB)
Installing collected packages: rapidfuzz, Levenshtein, python-Levenshtein
Successfully installed Levenshtein-0.22.0 python-Levenshtein-0.22.0 rapidfuzz-3.3.1
</pre>
<p>Enterキーを押すと、インストールが開始され、上記のように「Successfully installed」と表示されます。これが表示されれば、python-Levenshteinが正常にインストールされたことになります。</p>
<p>なお、今回はpython-Levenshteinのバージョン0.22.0をインストールしました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/python-installation-of-python-levenshtein-to-calculate-distance-and-similarity-of-string-edits/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>https://medium.com からデータを抽出するPythonラッパー「medium-api」のインストール</title>
		<link>https://laboratory.kazuuu.net/installation-of-medium-api-python-wrapper-to-extract-data-from-https-medium-com/</link>
					<comments>https://laboratory.kazuuu.net/installation-of-medium-api-python-wrapper-to-extract-data-from-https-medium-com/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Mon, 05 Aug 2024 19:50:35 +0000</pubDate>
				<category><![CDATA[Python【初歩から現場実務的なもの】]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17576</guid>

					<description><![CDATA[https://medium.com からデータを抽出するPythonラッパー「medium-api」のインストールについて解説しています。 「medium-api（https://github.com/weeping- [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>https://medium.com からデータを抽出するPythonラッパー「medium-api」のインストールについて解説しています。</p>
<p>「medium-api（<a href="https://github.com/weeping-angel/medium-api">https://github.com/weeping-angel/medium-api</a>）」は、Medium API上の Python ラッパーにより、MediumのWeb サイト（<a href="https://medium.com">https://medium.com</a>）からデータを抽出できる。なお、これはMediumが公式で配布しているものではなく、非公式であることを理解しておく必要があります。</p>
<h2>■Python</h2>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-16915" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/06/スクリーンショット-2023-06-11-082715-300x71.png" alt="" width="300" height="71" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/06/スクリーンショット-2023-06-11-082715-300x71.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/06/スクリーンショット-2023-06-11-082715-1024x244.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/06/スクリーンショット-2023-06-11-082715-768x183.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/06/スクリーンショット-2023-06-11-082715.png 1365w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>今回のPythonのバージョンは、「3.9.9」を使用しています。（Windows11）（pythonランチャーでの確認）</p>
<h2>■medium-apiをインストールする</h2>
<p>medium-apiをインストールを行いますが、今回はpipを経由してインストールを行うので、まずWindowsのコマンドプロンプトを起動します。</p>
<pre>pip install medium-api</pre>
<p>起動後、上記のコマンドを入力し、Enterキーを押します。</p>
<p>なお、今回は、pythonランチャーを使用しており、Python Version 3.9.9にインストールを行うために、バージョンの切り替えを行います。</p>
<pre>py -3.9 -m pip install medium-api</pre>
<p>切り替えるために、上記のコマンドを入力し、Enterキーを押します。</p>
<pre>Defaulting to user installation because normal site-packages is not writeable
Collecting medium-api
  Downloading medium_api-0.5.4-py3-none-any.whl (23 kB)
Installing collected packages: medium-api
Successfully installed medium-api-0.5.4
WARNING: You are using pip version 21.2.4; however, version 23.2.1 is available.
You should consider upgrading via the 'C:\Program Files\Python39\python.exe -m pip install --upgrade pip' command.
</pre>
<p>Enterキーを押すと、インストールが開始され、上記のように「Successfully installed」と表示されます。これが表示されれば、medium-apiが正常にインストールされたことになりますが、「WARNING」と表示されました。「WARNING」はエラーではなく警告で、インストールは行われているので、今回は一旦無視しています。</p>
<p>なお、今回はmedium-apiのバージョン0.5.4をインストールしました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/installation-of-medium-api-python-wrapper-to-extract-data-from-https-medium-com/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Python】さまざまなデータ構造の型システムを提供する「DataTypeSystem」のインストール</title>
		<link>https://laboratory.kazuuu.net/python-installation-of-datatypesystem-which-provides-a-type-system-for-various-data-structures/</link>
					<comments>https://laboratory.kazuuu.net/python-installation-of-datatypesystem-which-provides-a-type-system-for-various-data-structures/#respond</comments>
		
		<dc:creator><![CDATA[小林]]></dc:creator>
		<pubDate>Sun, 04 Aug 2024 19:50:11 +0000</pubDate>
				<category><![CDATA[Python【初歩から現場実務的なもの】]]></category>
		<guid isPermaLink="false">https://laboratory.kazuuu.net/?p=17561</guid>

					<description><![CDATA[さまざまなデータ構造の型システムを提供する「DataTypeSystem」のインストールについて解説しています。 「DataTypeSystem（https://github.com/antononcube/Python [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>さまざまなデータ構造の型システムを提供する「DataTypeSystem」のインストールについて解説しています。</p>
<p>「DataTypeSystem（<a href="https://github.com/antononcube/Python-packages/tree/main/DataTypeSystem">https://github.com/antononcube/Python-packages/tree/main/DataTypeSystem</a>）」は、完全な配列に強制変換できるさまざまなデータ構造の型システムを提供しているPythonライブラリです。</p>
<h2>■Python</h2>
<p><a href="https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334.png"><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-16692" src="https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-300x139.png" alt="" width="300" height="139" srcset="https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-300x139.png 300w, https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-1024x475.png 1024w, https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334-768x356.png 768w, https://laboratory.kazuuu.net/wp-content/uploads/2023/05/スクリーンショット-2023-05-29-120334.png 1250w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>今回のPythonのバージョンは、「3.10.9」を使用しています。（Windows11）（pythonランチャーでの確認）</p>
<h2>■DataTypeSystemをインストールする</h2>
<p>DataTypeSystemをインストールを行いますが、今回はpipを経由してインストールを行うので、まずWindowsのコマンドプロンプトを起動します。</p>
<pre>pip install DataTypeSystem</pre>
<p>起動後、上記のコマンドを入力し、Enterキーを押します。</p>
<p>なお、今回は、pythonランチャーを使用しており、Python Version 3.10.9にインストールを行うために、バージョンの切り替えを行います。</p>
<pre>py -3.10 -m pip install DataTypeSystem</pre>
<p>切り替えるために、上記のコマンドを入力し、Enterキーを押します。</p>
<pre>Defaulting to user installation because normal site-packages is not writeable
Collecting DataTypeSystem
  Downloading DataTypeSystem-0.1.0-py3-none-any.whl (7.0 kB)
Installing collected packages: DataTypeSystem
Successfully installed DataTypeSystem-0.1.0
</pre>
<p>Enterキーを押すと、インストールが開始され、上記のように「Successfully installed」と表示されます。これが表示されれば、DataTypeSystemが正常にインストールされたことになりますが、「WARNING」と表示されました。「WARNING」はエラーではなく警告で、インストールは行われているので、今回は一旦無視しています。<br />
なお、今回はDataTypeSystemのバージョン0.1.0をインストールしました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://laboratory.kazuuu.net/python-installation-of-datatypesystem-which-provides-a-type-system-for-various-data-structures/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
