【プログラミング実践講座-01】出力されたAIコードの解説と実際に書いたコード


Python
投稿日:
【プログラミング実践講座-01】出力されたAIコードの解説と実際に書いたコード

ここでは動画で紹介したコードを詳しく解説しています。

動画では省略した部分の解説になるので、もし動画を見ていない方は以下から見てもらえればと思います。

AIで作られたコード解説

今回の動画でAIが出力したコードは以下にになります。

コード: crawler.py
import csv
import sys
import time
from dataclasses import dataclass
from typing import Iterable, Optional
from urllib.parse import urljoin

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, WebDriverException


# =========
# Config
# =========

@dataclass(frozen=True)
class Config:
    start_url: str = "https://code.t-busi.com/"
    mode: str = "A"  # "A" or "B"
    output_csv: str = "export.csv"
    timeout_sec: int = 20
    # 例外時の方針:継続 or 即終了(設計図では「継続推奨」):contentReference[oaicite:3]{index=3}
    continue_on_error: bool = True


# =========
# Logger
# =========

class Logger:
    def info(self, msg: str) -> None:
        print(f"[INFO] {msg}")

    def warn(self, msg: str) -> None:
        print(f"[WARN] {msg}", file=sys.stderr)

    def error(self, msg: str) -> None:
        print(f"[ERROR] {msg}", file=sys.stderr)


# =========
# Driver Manager(表示あり)
# =========

class DriverManager:
    def __init__(self, cfg: Config):
        self.cfg = cfg

    def create(self) -> webdriver.Chrome:
        options = Options()
        # 「表示あり」なので headless は使わない :contentReference[oaicite:4]{index=4}
        options.add_argument("--disable-gpu")
        options.add_argument("--window-size=1280,900")
        options.add_argument("--lang=ja-JP")
        # 余計なログ抑制(必要なら外してください)
        options.add_experimental_option("excludeSwitches", ["enable-logging"])

        driver = webdriver.Chrome(options=options)
        driver.set_page_load_timeout(self.cfg.timeout_sec)
        return driver


# =========
# Navigator(URL遷移が基本)
# =========

class Navigator:
    def __init__(self, driver: webdriver.Chrome, cfg: Config):
        self.driver = driver
        self.cfg = cfg
        self.waiter = WebDriverWait(driver, cfg.timeout_sec)

    def goto(self, url: str) -> None:
        self.driver.get(url)

    def wait_css(self, css: str) -> None:
        self.waiter.until(EC.presence_of_element_located((By.CSS_SELECTOR, css)))

    # 将来拡張用(クリック遷移は補助):contentReference[oaicite:5]{index=5}
    def click(self, css: str) -> None:
        el = self.waiter.until(EC.element_to_be_clickable((By.CSS_SELECTOR, css)))
        el.click()


# =========
# Extractors
# =========

KNOWN_CATEGORIES = {"Env", "Python", "Django", "VBA", "Deploy", "Security"}

class ListExtractor:
    """
    一覧ページ抽出:
    - 記事カード領域: main section.grid
    - 記事URL: main section.grid article a[href]
    - タイトル: main section.grid article h3
    - ページング: nav[aria-label="ページネーション"] a[href]
    :contentReference[oaicite:6]{index=6}
    """
    GRID_SCOPE = "main section.grid"
    ARTICLE_CSS = "main section.grid article"
    ARTICLE_LINK_CSS = "a[href]"
    TITLE_CSS = "h2"
    PAGINATION_LINKS = 'nav[aria-label="ページネーション"] a[href]'

    def __init__(self, driver: webdriver.Chrome):
        self.driver = driver

    def iter_article_cards(self) -> Iterable[webdriver.remote.webelement.WebElement]:
        return self.driver.find_elements(By.CSS_SELECTOR, self.ARTICLE_CSS)

    def extract_card_url(self, article_el) -> Optional[str]:
        try:
            a = article_el.find_element(By.CSS_SELECTOR, self.ARTICLE_LINK_CSS)
            return a.get_attribute("href")
        except Exception:
            return None

    def extract_card_title(self, article_el) -> str:
        # 設計図通り h3 を基本にしつつ、無ければリンクテキストにフォールバック
        try:
            return article_el.find_element(By.CSS_SELECTOR, self.TITLE_CSS).text.strip()
        except Exception:
            try:
                a = article_el.find_element(By.CSS_SELECTOR, self.ARTICLE_LINK_CSS)
                return a.text.strip()
            except Exception:
                return ""

    def extract_card_category(self, article_el) -> str:
        """
        カテゴリバッジ(span)とタグ(例:#Python)の span が混同し得るため、
        span群から「既知カテゴリ(Env/Python/...)」に一致するものを優先して拾います。
        :contentReference[oaicite:7]{index=7}
        """
        spans = article_el.find_elements(By.CSS_SELECTOR, "span")
        texts = [s.text.strip() for s in spans if s.text and s.text.strip()]
        for t in texts:
            if t in KNOWN_CATEGORIES:
                return t
        # それでも無ければ、先頭候補を返す(サイト側表示が変わったとき用)
        return texts[0] if texts else ""

    def extract_pagination_urls(self, base_url: str) -> list[str]:
        urls: list[str] = []
        for a in self.driver.find_elements(By.CSS_SELECTOR, self.PAGINATION_LINKS):
            href = a.get_attribute("href")
            if not href:
                continue
            # 相対が来る可能性もあるので urljoin
            urls.append(urljoin(base_url, href))
        # 重複除去(順序維持)
        seen = set()
        uniq = []
        for u in urls:
            if u not in seen:
                uniq.append(u)
                seen.add(u)
        return uniq


class DetailExtractor:
    """
    詳細ページ抽出(パターンB用):
    タイトルは h1 を第一候補、無ければ OGタイトルなどにフォールバック。
    カテゴリーは「既知カテゴリ」の文字列をページ内から探索して推定。
    (詳細DOMの確定セレクタは設計図の「今後の確定事項」に該当):contentReference[oaicite:8]{index=8}
    """
    def __init__(self, driver: webdriver.Chrome):
        self.driver = driver

    def extract_title(self) -> str:
        # 第一候補: h1
        h1s = self.driver.find_elements(By.CSS_SELECTOR, "main h1, article h1, h1")
        for h in h1s:
            t = h.text.strip()
            if t:
                return t

        # フォールバック: titleタグ
        try:
            return self.driver.title.strip()
        except Exception:
            return ""

    def extract_category(self) -> str:
        # 既知カテゴリをページの可視テキストから探索(UI変更に強い)
        body_text = ""
        try:
            body_text = self.driver.find_element(By.TAG_NAME, "body").text
        except Exception:
            pass
        for cat in KNOWN_CATEGORIES:
            if cat in body_text:
                return cat
        return ""


# =========
# Storage(CSV)
# =========

class CsvStorage:
    def __init__(self, path: str):
        self.path = path

    def write(self, rows: list[dict[str, str]]) -> None:
        # UTF-8(必要ならBOM:utf-8-sig に変更):contentReference[oaicite:9]{index=9}
        with open(self.path, "w", newline="", encoding="utf-8") as f:
            writer = csv.DictWriter(f, fieldnames=["URL", "タイトル", "カテゴリー"])
            writer.writeheader()
            writer.writerows(rows)


# =========
# Runner
# =========

class Runner:
    def __init__(self, cfg: Config, logger: Logger):
        self.cfg = cfg
        self.log = logger

        self.pages_queue: list[str] = []
        self.seen_pages: set[str] = set()
        self.seen_articles: set[str] = set()
        self.rows: list[dict[str, str]] = []
        self.failed_urls: list[str] = []

    def run(self) -> None:
        dm = DriverManager(self.cfg)
        driver = dm.create()
        input('画面が表示されたらEnter')
        nav = Navigator(driver, self.cfg)
        list_ex = ListExtractor(driver)
        detail_ex = DetailExtractor(driver)
        storage = CsvStorage(self.cfg.output_csv)

        try:
            if self.cfg.mode.upper() == "A":
                self._run_mode_a(nav, list_ex)
            elif self.cfg.mode.upper() == "B":
                self._run_mode_b(nav, list_ex, detail_ex)
            else:
                raise ValueError("mode は 'A' または 'B' を指定してください。")

            storage.write(self.rows)
            self.log.info(f"CSV出力完了: {self.cfg.output_csv}{len(self.rows)}件)")

            if self.failed_urls:
                self.log.warn(f"失敗URL: {len(self.failed_urls)}件")
                for u in self.failed_urls[:30]:
                    self.log.warn(f"  - {u}")
        finally:
            driver.quit()

    def _run_mode_a(self, nav: Navigator, list_ex: ListExtractor) -> None:
        # 設計図:一覧のみで完結 :contentReference[oaicite:10]{index=10}
        self.pages_queue = [self.cfg.start_url]

        page_count = 0
        while self.pages_queue:
            page_url = self.pages_queue.pop(0)
            if page_url in self.seen_pages:
                continue
            self.seen_pages.add(page_url)
            page_count += 1

            self.log.info(f"[A] 一覧ページへ遷移: {page_url}{page_count}ページ目)")
            try:
                nav.goto(page_url)
                nav.wait_css(ListExtractor.GRID_SCOPE)
            except TimeoutException:
                self._handle_failure(page_url, "一覧ページのgrid待機でタイムアウト")
                continue

            # 記事カード列挙
            for article in list_ex.iter_article_cards():
                url = list_ex.extract_card_url(article)
                if not url:
                    continue
                url = urljoin(page_url, url)  # 念のため
                if url in self.seen_articles:
                    continue
                self.seen_articles.add(url)

                title = list_ex.extract_card_title(article)
                category = list_ex.extract_card_category(article)

                self.rows.append({"URL": url, "タイトル": title, "カテゴリー": category})

            self.log.info(f"  取得済み記事数: {len(self.rows)}")

            # ページングURL抽出
            for p in list_ex.extract_pagination_urls(page_url):
                if p not in self.seen_pages:
                    self.pages_queue.append(p)

    def _run_mode_b(self, nav: Navigator, list_ex: ListExtractor, detail_ex: DetailExtractor) -> None:
        # 設計図:一覧でURL収集 → 詳細で確定 :contentReference[oaicite:11]{index=11}
        self.pages_queue = [self.cfg.start_url]

        page_count = 0
        while self.pages_queue:
            page_url = self.pages_queue.pop(0)
            if page_url in self.seen_pages:
                continue
            self.seen_pages.add(page_url)
            page_count += 1

            self.log.info(f"[B] 一覧ページへ遷移(URL収集): {page_url}{page_count}ページ目)")
            try:
                nav.goto(page_url)
                nav.wait_css(ListExtractor.GRID_SCOPE)
            except TimeoutException:
                self._handle_failure(page_url, "一覧ページのgrid待機でタイムアウト")
                continue

            for a in self._extract_article_urls_only(list_ex, page_url):
                self.seen_articles.add(a)

            for p in list_ex.extract_pagination_urls(page_url):
                if p not in self.seen_pages:
                    self.pages_queue.append(p)

        self.log.info(f"[B] 詳細ページ収集対象: {len(self.seen_articles)}件")

        idx = 0
        for url in list(self.seen_articles):
            idx += 1
            self.log.info(f"[B] 詳細へ遷移: {url}{idx}/{len(self.seen_articles)})")
            try:
                nav.goto(url)
                # タイトル要素の確定が未完なので、とりあえず main/h1 を待機 :contentReference[oaicite:12]{index=12}
                nav.wait_css("main h1, article h1, h1")
                title = detail_ex.extract_title()
                category = detail_ex.extract_category()
                self.rows.append({"URL": url, "タイトル": title, "カテゴリー": category})
            except TimeoutException:
                self._handle_failure(url, "詳細ページのh1待機でタイムアウト")
                continue
            except WebDriverException as e:
                self._handle_failure(url, f"WebDriverException: {e}")
                continue

    def _extract_article_urls_only(self, list_ex: ListExtractor, base_url: str) -> list[str]:
        urls: list[str] = []
        for article in list_ex.iter_article_cards():
            u = list_ex.extract_card_url(article)
            if not u:
                continue
            u = urljoin(base_url, u)
            if u in self.seen_articles:
                continue
            urls.append(u)
        return urls

    def _handle_failure(self, url: str, reason: str) -> None:
        self.failed_urls.append(url)
        self.log.warn(f"失敗: {url} / {reason}")
        if not self.cfg.continue_on_error:
            raise RuntimeError(f"失敗により停止: {url} / {reason}")


# =========
# Entry
# =========

def main():
    # 手動実行想定(設計図どおり):contentReference[oaicite:13]{index=13}
    cfg = Config(
        start_url="https://code.t-busi.com/",
        mode="A",              # まずはA(一覧完結・高速)推奨 :contentReference[oaicite:14]{index=14}
        output_csv="export_02.csv",
        timeout_sec=20,
        continue_on_error=True,
    )
    logger = Logger()
    Runner(cfg, logger).run()


if __name__ == "__main__":
    main()

Configの解説

コード: python
@dataclass(frozen=True)
class Config:
    start_url: str = "https://code.t-busi.com/"
    mode: str = "A"  # "A" or "B"
    output_csv: str = "export.csv"
    timeout_sec: int = 20
    continue_on_error: bool = True

こちらはプログラム全体の設定値を1か所にまとめるためのクラスになります。

ちなみに@dataclass(frozen=True) で、生成後に値を変更できない設計になっています。

各項目の意味は

  • start_url:最初に開くURL(トップ/一覧)
  • mode:処理モード “A” or “B”
  • output_csv:出力するCSVファイル名
  • timeout_sec:Seleniumの待機時間
  • continue_on_error:失敗が出ても続行するか

という感じになっています。

Loggerの解説

コード: python
class Logger:
    def info(self, msg: str) -> None:
        print(f"[INFO] {msg}")

    def warn(self, msg: str) -> None:
        print(f"[WARN] {msg}", file=sys.stderr)

    def error(self, msg: str) -> None:
        print(f"[ERROR] {msg}", file=sys.stderr)

この部分は処理の状況を確認する(ログを出す)ための部分になります。

何か問題が起きた時や、処理が完了した時にコマンドプロンプトにメッセージを表示するために使うものです。

DriverManager

コード: python
class DriverManager:
    def __init__(self, cfg: Config):
        self.cfg = cfg

    def create(self) -> webdriver.Chrome:
        options = Options()
        options.add_argument("--disable-gpu")
        options.add_argument("--window-size=1280,900")
        options.add_argument("--lang=ja-JP")
        options.add_experimental_option("excludeSwitches", ["enable-logging"])

        driver = webdriver.Chrome(options=options)
        driver.set_page_load_timeout(self.cfg.timeout_sec)
        return driver

ここは実際にブラウザを生成して戻り値として返す役割になっています。

最初の【init】というのは、インストラクタでDriverManagerのインスタンスが生成された時に実行されます。

createが呼び出されるとseleniumのwebdriverを使用して、ブラウザを生成します。

オプションの内容としては

  • disable-gpu:GPUを使わないようにするオプション
  • window-size=1280,900:起動するChromeウィンドウのサイズを幅1280、高さ900に固定
  • lang=ja-JP:ブラウザの言語を日本語に寄せる
  • excludeSwitches, [“enable-logging”]:余計なログを出さないようにする

こういった設定になっています。

コード: python
class Navigator:
    def __init__(self, driver: webdriver.Chrome, cfg: Config):
        self.driver = driver
        self.cfg = cfg
        self.waiter = WebDriverWait(driver, cfg.timeout_sec)

    def goto(self, url: str) -> None:
        self.driver.get(url)

    def wait_css(self, css: str) -> None:
        self.waiter.until(EC.presence_of_element_located((By.CSS_SELECTOR, css)))

    def click(self, css: str) -> None:
        el = self.waiter.until(EC.element_to_be_clickable((By.CSS_SELECTOR, css)))
        el.click()

ここはseleniumの操作の部分になります。

「ページ遷移→要素が出るまで待機」

これをここで関数として作成して、ページ移動時に使用するという形です。

各関数について

  • goto(url):指定URLへ移動
  • wait_css(css):指定CSSセレクタの要素がDOM上に現れるまで待機
  • click(css):クリック可能になるまで待ってからクリック

ListExtractorの解説

コード: python
class ListExtractor:
    """
    一覧ページ抽出:
    - 記事カード領域: main section.grid
    - 記事URL: main section.grid article a[href]
    - タイトル: main section.grid article h3
    - ページング: nav[aria-label="ページネーション"] a[href]
    :contentReference[oaicite:6]{index=6}
    """
    GRID_SCOPE = "main section.grid"
    ARTICLE_CSS = "main section.grid article"
    ARTICLE_LINK_CSS = "a[href]"
    TITLE_CSS = "h2"
    PAGINATION_LINKS = 'nav[aria-label="ページネーション"] a[href]'

    def __init__(self, driver: webdriver.Chrome):
        self.driver = driver

    def iter_article_cards(self) -> Iterable[webdriver.remote.webelement.WebElement]:
        return self.driver.find_elements(By.CSS_SELECTOR, self.ARTICLE_CSS)

    def extract_card_url(self, article_el) -> Optional[str]:
        try:
            a = article_el.find_element(By.CSS_SELECTOR, self.ARTICLE_LINK_CSS)
            return a.get_attribute("href")
        except Exception:
            return None

    def extract_card_title(self, article_el) -> str:
        # 設計図通り h3 を基本にしつつ、無ければリンクテキストにフォールバック
        try:
            return article_el.find_element(By.CSS_SELECTOR, self.TITLE_CSS).text.strip()
        except Exception:
            try:
                a = article_el.find_element(By.CSS_SELECTOR, self.ARTICLE_LINK_CSS)
                return a.text.strip()
            except Exception:
                return ""

    def extract_card_category(self, article_el) -> str:
        """
        カテゴリバッジ(span)とタグ(例:#Python)の span が混同し得るため、
        span群から「既知カテゴリ(Env/Python/...)」に一致するものを優先して拾います。
        :contentReference[oaicite:7]{index=7}
        """
        spans = article_el.find_elements(By.CSS_SELECTOR, "span")
        texts = [s.text.strip() for s in spans if s.text and s.text.strip()]
        for t in texts:
            if t in KNOWN_CATEGORIES:
                return t
        # それでも無ければ、先頭候補を返す(サイト側表示が変わったとき用)
        return texts[0] if texts else ""

    def extract_pagination_urls(self, base_url: str) -> list[str]:
        urls: list[str] = []
        for a in self.driver.find_elements(By.CSS_SELECTOR, self.PAGINATION_LINKS):
            href = a.get_attribute("href")
            if not href:
                continue
            # 相対が来る可能性もあるので urljoin
            urls.append(urljoin(base_url, href))
        # 重複除去(順序維持)
        seen = set()
        uniq = []
        for u in urls:
            if u not in seen:
                uniq.append(u)
                seen.add(u)
        return uniq

ここはコメントで書いてある通りの内容です。

一覧ページからfind_elementsのCSS_SELECTORに与える引数を変数で指定して、要素を探しています。

find_elementとfind_elementsは要素を指定して、ページからその要素を含む場所を探すseleniumの機能です。

・finde_element:指定した要素の最初のデータを返す。要素がなければエラー。

・find_elements:指定した要素を含む全てのデータをリストで返す。要素がない場合はNone。

コード: python
GRID_SCOPE = "main section.grid"
ARTICLE_CSS = "main section.grid article"
ARTICLE_LINK_CSS = "a[href]"
TITLE_CSS = "h2"
PAGINATION_LINKS = 'nav[aria-label="ページネーション"] a[href]'

この部分が今回指定している要素になるので、サイトの構成や別サイトで取得する場合は、この部分を修正する感じです。

DetailExtractorの解説

コード: python
class DetailExtractor:
    """
    詳細ページ抽出(パターンB用):
    タイトルは h1 を第一候補、無ければ OGタイトルなどにフォールバック。
    カテゴリーは「既知カテゴリ」の文字列をページ内から探索して推定。
    (詳細DOMの確定セレクタは設計図の「今後の確定事項」に該当):contentReference[oaicite:8]{index=8}
    """
    def __init__(self, driver: webdriver.Chrome):
        self.driver = driver

    def extract_title(self) -> str:
        # 第一候補: h1
        h1s = self.driver.find_elements(By.CSS_SELECTOR, "main h1, article h1, h1")
        for h in h1s:
            t = h.text.strip()
            if t:
                return t
        # フォールバック: titleタグ
        try:
            return self.driver.title.strip()
        except Exception:
            return ""

    def extract_category(self) -> str:
        # 既知カテゴリをページの可視テキストから探索(UI変更に強い)
        body_text = ""
        try:
            body_text = self.driver.find_element(By.TAG_NAME, "body").text
        except Exception:
            pass
        for cat in KNOWN_CATEGORIES:
            if cat in body_text:
                return cat
        return ""

ここは記事のページから情報を取得する方法です。今回で言えばモードB用のコードになります。

●extract_title()

まずページ内のh1を探してタイトルにする。

取れない場合はdriver.title(titleタグ相当)で再度実行。

それでもない場合には、空白を返すという処理です。

●extract_category()

まずbody_textという変数に記事ページ全体のテキスト(body.text)を取っています。

その後にKNOWN_CATEGORIESという自分で推測したカテゴリが含まれていればそれをカテゴリとみなす処理です。

これは要素の指定が間違っていても動くものではあるのですが、、

テキスト内にKNOWN_CATEGORIESで決めた文字列(PythonならPython)が入ってると、それをカテゴリとして認識します。

これは誤判定の確率が、かなり高いため個人的に使うのは非推奨です。

CsvStorageの解説

コード: python
class CsvStorage:
    def __init__(self, path: str):
        self.path = path

    def write(self, rows: list[dict[str, str]]) -> None:
        with open(self.path, "w", newline="", encoding="utf-8") as f:
            writer = csv.DictWriter(f, fieldnames=["URL", "タイトル", "カテゴリー"])
            writer.writeheader()
            writer.writerows(rows)

ここはCSVの出力です。

  • rows:dictの配列をCSVに保存
  • writeheader:ヘッダー行(URL, タイトル, カテゴリー)を先頭につける

実行について

main関数でRunnerを実行しています。

この時にcfgとしてmodeがAかBかを指定して、

  • Aの場合:_run_mode_aが実行
  • Bの場合:_run_mode_bが実行

という分岐がされています。

ちなみにこの部分ですね。

コード: python
if self.cfg.mode.upper() == "A":
    self._run_mode_a(nav, list_ex)
elif self.cfg.mode.upper() == "B":
    self._run_mode_b(nav, list_ex, detail_ex)
else:
    raise ValueError("mode は 'A' または 'B' を指定してください。")

これでAの場合には、URL・タイトル・カテゴリが取得出来て、CSVが出力できました。

Bの場合には、カテゴリが取得できないので修正が必要という感じです。

僕が作ったコード

今回AIが作ったコードはエラー処理が多いせいで、かなり長いコードになっています。

なので今回のコードで使える部分として、

  • ブラウザーの開き方
  • URLを指定して遷移する方法
  • 要素を指定してデータを取得

この3つの方法をAIのコードから抽出して以下のコードを実装しました。

コード: crawler_ver02.py
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import csv


class Browser:
    def __init__(self):
        self.browser = webdriver.Chrome()

    def move_browser(self, url):
        self.browser.get(url)

    def extract_data(self):
        main_url = 'https://code.t-busi.com/'
        self.move_browser(main_url)
        get_page_num = 1
        out_csv_data_list = []
        while True:
            article_data_list = self.browser.find_elements(By.TAG_NAME, 'article')
            for article_data in article_data_list:
                category = article_data.find_element(By.TAG_NAME, 'span').text
                title = article_data.find_element(By.TAG_NAME, 'h3').text
                article_url = article_data.find_element(By.TAG_NAME, 'a').get_attribute('href')
                out_csv_data_list.append([article_url, title, category])
            # 今回9記事未満の場合には終了する
            if len(article_data_list) < 9:
                print(f'{get_page_num}ページで記事を全て取得したので終了します。')
                break
            # サーバーに負荷をかけないように待機
            time.sleep(1)
            # ページ番号で記事一覧の次のページに遷移
            get_page_num += 1
            next_url = f'{main_url}/page/{get_page_num}/'
            self.move_browser(next_url)
        return out_csv_data_list

    def __del__(self):
        print('ブラウザを閉じます')
        self.browser.quit()


def export_csv(out_csv_data_list, csv_name):
    header = ['URL', 'Title', 'Category']
    with open(csv_name, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow(header)
        writer.writerows(out_csv_data_list)


if __name__ == "__main__":
    # クラスをインスタンス化
    browser = Browser()
    # 記事一覧のデータを取得する
    out_csv_data_list = browser.extract_data()
    # 取得したデータでCSVに出力する
    out_csv_name = 'output.csv'
    export_csv(out_csv_data_list, out_csv_name)

エラー処理は入っていないですが、今回の出力したい内容を出力出来るようになっています。

内容としては

  • インストラクタでブラウザを開いてインスタンス変数に格納
  • move_browserで引数として指定したurlに移動
  • extract_dataで記事一覧のページからデータを取得
  • export_csvで取得したデータをcsvファイルに出力

こういった内容になっています。

ということで、動画で出ていたコードを解説してきました。

今回AIで作ったコードは、長くてちょっと難解なコードだと思います。

ただエラー処理などを含めると確かに、こういったコードになることも多いです。

こういった内容を決めて再度AIに作ってもらったり、作られたコードから自分で必要な機能を抽出して作る。

この方法でやっていくと自分が思ったような実装が出来るかと思います。

質問はこちら
もし今回のことやプログラミングについて分からないことがあれば、回答していくので、気軽に以下から聞いてくださいね。
> 質問募集中です!

※頂いた質問は動画コンテンツとして回答していく予定です。



All Categories

Advertisement