12【超初心者向け】PythonでWebスクレイピング:Seleniumを使ってデータを取得する方法~環境構築と全体の流れの説明~|友季子@Python学習中 (2024)

はじめに


こんにちは、TechCommitの友季子です(^^) この記事では、PythonとSeleniumを使用して、Webスクレイピングを行い、取得したデータを処理する方法をステップバイステップで超初心者向けに解説します!


1.クローラー開発のサンプル

今回は、GoogleビジネスプロフィールのData抽出を例にあげて説明します。電話番号を基点にしたデータ取得を行います。

import timeimport reimport randomimport pandas as pdfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.chrome.service import Servicefrom selenium.webdriver.common.keys import Keysfrom webdriver_manager.chrome import ChromeDriverManagerfrom bs4 import BeautifulSoup# 入力ファイルと出力ファイルのパスを定義しますinput_file = "C:\\Users\\USER\\Desktop\\PhoneNumberList.csv"output_file = "C:\\Users\\USER\\Desktop\\matuosantestgbp0706.csv"# CSVファイルから電話番号を読み取る関数を定義しますdef read_csv(file_path): df = pd.read_csv(file_path) phone_numbers = df['phone_number'].dropna().tolist() print(f"{len(phone_numbers)}件の電話番号の読み込みができたにゃ(=^・^=)!") return phone_numbers# Google検索からビジネス情報を取得する関数を定義しますdef fetch_business_info(driver, phone_number): driver.get("https://www.google.co.jp/") time.sleep(random.uniform(0.005, 0.006)) # ランダムな待機時間 search_box = driver.find_element(By.NAME, 'q') # 検索ボックスを取得 search_box.click() time.sleep(random.uniform(0.008, 0.004)) # ランダムな待機時間 search_box.send_keys(phone_number) time.sleep(random.uniform(0.01, 0.018)) # ランダムな待機時間 search_box.send_keys(Keys.ENTER) time.sleep(random.uniform(1, 2)) # ランダムな待機時間 business_info = {} try: # Nameの取得のために複数の方法を試します business_info['Name'] = driver.find_element(By.XPATH, '//*[@id="Sva75c"]/div[2]/div[2]/div/div[2]/c-wiz/div/c-wiz[1]/c-wiz/c-wiz/c-wiz[1]/div/div/div[2]/div[1]/div/div/h3').text except Exception as e: print(f"Name not found via XPath method 1 for {phone_number}: {e}") try: business_info['Name'] = driver.find_element(By.XPATH, '/html/body/div[8]/div/div/div/div/div/div/c-wiz/div/div[2]/div[2]/div/div[2]/c-wiz/div/c-wiz[1]/c-wiz/c-wiz/c-wiz[1]/div/div/div[2]/div[1]/div/div/h3').text except Exception as e: print(f"Name not found via XPath method 2 for {phone_number}: {e}") try: business_info['Name'] = driver.find_element(By.CSS_SELECTOR, 'h3').text except Exception as e: print(f"Name not found for {phone_number}: {e}") business_info['Name'] = '' try: business_info['Rating'] = driver.find_element(By.CSS_SELECTOR, 'span.Aq14fc').text except Exception as e: print(f"Rating not found for {phone_number}: {e}") business_info['Rating'] = '' try: business_info['Reviews Count'] = driver.find_element(By.CSS_SELECTOR, '.hqzQac span span').text except Exception as e: print(f"Reviews Count not found for {phone_number}: {e}") business_info['Reviews Count'] = '' try: business_info['Address'] = driver.find_element(By.CSS_SELECTOR, 'span.LrzXr').text except Exception as e: print(f"Address not found for {phone_number}: {e}") business_info['Address'] = '' try: business_info['Phone'] = driver.find_element(By.CSS_SELECTOR, 'span.LrzXr.zdqRlf.kno-fv').text except Exception as e: print(f"Phone not found for {phone_number}: {e}") business_info['Phone'] = '' try: # BeautifulSoupでページを解析 soup = BeautifulSoup(driver.page_source, 'html.parser') hours_table = soup.find('table', {'class': 'WgFkxc'}) # 営業時間の表を見つける hours = "\n".join([row.text for row in hours_table.find_all('tr')]) # 営業時間を取得 business_info['Hours'] = hours except Exception as e: print(f"Hours not found for {phone_number}: {e}") business_info['Hours'] = '' try: business_info['Website'] = driver.find_element(By.CSS_SELECTOR, 'a.ab_button').get_attribute('href') except Exception as e: print(f"Website not found for {phone_number}: {e}") business_info['Website'] = '' # 予算情報を取得する処理 try: # 検索結果のHTMLを解析するためにBeautifulSoupを使用 soup = BeautifulSoup(driver.page_source, 'html.parser') # 予算情報を含む可能性のある要素を見つける budget_element = soup.find('span', text=re.compile(r'¥\d+~¥\d+')) business_info['Budget'] = budget_element.text if budget_element else '' except Exception as e: print(f"Budget not found for {phone_number}: {e}") business_info['Budget'] = '' # 業種情報を取得する処理 try: business_info['Category'] = driver.find_element(By.CSS_SELECTOR, 'span.YhemCb').text except Exception as e: print(f"Category not found for {phone_number}: {e}") business_info['Category'] = '' # 正確な業種情報を抽出 try: category_info = driver.find_element(By.XPATH, '//*[@id="yDmH0d"]/c-wiz[3]/div/div/div[2]/div/div[1]/div[3]/div[1]/span[3]/span[3]').text business_info['Category'] = category_info except Exception as e: print(f"Category (XPath specific) not found for {phone_number}: {e}") # Categoryに予算と業種を連結 if business_info['Budget'] and business_info['Category']: business_info['Category'] = f"{business_info['Category']} ({business_info['Budget']})" elif business_info['Budget']: business_info['Category'] = business_info['Budget'] # 業種をさらに判定する処理を追加 categories = ["ファーストフード", "花屋", "居酒屋", "整体", "パン屋", "ラーメン", "焼肉", "コーヒーショップ", "ハンバーガー", "カフェ", "理容", "美容","小売り","フラワーショップ"] detected_category = None try: category_elements = driver.find_elements(By.CSS_SELECTOR, 'div.yuRUbf a h3') for element in category_elements: for category in categories: if category in element.text: detected_category = category break if detected_category: break except: pass # 見つかった業種を追加 if detected_category: business_info['Category'] = detected_category return business_info# 住所から郵便番号と都道府県を削除する関数を定義しますdef remove_post_code_and_prefecture(address): address = re.sub(r'〒?\d{3}-\d{4}', '', address).strip() # 都道府県のリスト prefectures = [ "北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県", "茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県", "新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県", "静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県", "和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", "高知県", "福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県" ] # 都道府県の抽出 for prefecture in prefectures: if address.startswith(prefecture): return prefecture, address[len(prefecture):].strip() return "", address# CSVファイルにデータを書き込む関数を定義しますdef write_to_csv(output_path, headers, data): df = pd.DataFrame(data, columns=headers) df.to_csv(output_path, index=False, encoding='utf-8-sig')# メイン関数を定義しますdef main(): phone_numbers = read_csv(input_file) options = webdriver.ChromeOptions() driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) headers = ["Name", "Address", "Phone", "県", "Hours", "Website", "Category", "Rating", "Reviews Count"] extracted_data = [] for phone_number in phone_numbers: retries = 3 # 再試行回数を定義 business_info = {} for attempt in range(retries): business_info = fetch_business_info(driver, phone_number) if business_info.get("Name"): break # 名前が取得できた場合、ループを抜ける print(f"Retry {attempt + 1} for {phone_number}") time.sleep(random.uniform(2, 5)) # 再試行前にランダムな待機時間 address = business_info.get("Address", "") prefecture, address = remove_post_code_and_prefecture(address) # 住所から郵便番号と都道府県を削除 extracted_data.append([ business_info.get("Name", ""), address, business_info.get("Phone", ""), prefecture, # 県情報を追加 business_info.get("Hours", ""), business_info.get("Website", ""), business_info.get("Category", ""), business_info.get("Rating", ""), business_info.get("Reviews Count", "") ]) write_to_csv(output_file, headers, extracted_data) driver.quit()# メイン関数を実行if __name__ == "__main__": main()print("CSVファイルに抽出結果が出力されたにゃー(=^・^=)。") #Googleビジネスプロフィールのクローラー _8/13_植竹さんが欲しい仕様にヘッダーと電話番号ハイフンなし以外実現、早い※遅いときとデータ欠損件数同じくらい

2.スクレイピングのサンプル

※GoogleビジネスプロフィールのData抽出を例にあげて説明します。

import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.chrome.service import Servicefrom webdriver_manager.chrome import ChromeDriverManager# セレニウムの設定options = webdriver.ChromeOptions()options.add_argument("--headless") # ヘッドレスモードで実行します。driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)# Google検索結果のURL※無くてもOKurl = "https://www.google.com/search?q=%E3%83%9E%E3%82%AF%E3%83%89%E3%83%8A%E3%83%AB%E3%83%89+%E8%95%A8%E6%9D%B1%E5%8F%A3%E5%BA%97&oq=%E3%83%9E%E3%82%AF%E3%83%89%E3%83%8A%E3%83%AB%E3%83%89+%E8%95%A8%E6%9D%B1%E5%8F%A3%E5%BA%97&gs_lcrp=EgZjaHJvbWUqCQgAEEUYOxiABDIJCAAQRRg7GIAEMgcIARAAGIAEMgcIAhAAGIAEMgoIAxAAGIAEGKIEMgoIBBAAGIAEGKIEMgoIBRAAGIAEGKIEMgoIBhAAGIAEGKIEMgYIBxBFGD3SAQc5MDBqMGo3qAIIsAIB&sourceid=chrome&ie=UTF-8#ip=1"# ページを開くdriver.get(urlxxx)# ページの読み込み待機 5秒待機time.sleep(5)# Google My Businessの情報を取得business_info = {}try:business_info['namexx'] = driver.find_element(By.CSS_SELECTOR, '#rhs > div.kp-wholepage-osrp > div > div > div > div:nth-child(2) > div > div > div.nwVKo > div.loJjTe > div').textexcept:passtry:business_info['rating'] = driver.find_element(By.CSS_SELECTOR, 'div.Aq14fc').textexcept:passtry:business_info['reviews_count'] = driver.find_element(By.CSS_SELECTOR, 'span.EymY4b').textexcept:passtry:business_info['address'] = driver.find_element(By.CSS_SELECTOR, 'span.LrzXr').textexcept:passtry:business_info['phone'] = driver.find_element(By.CSS_SELECTOR, 'span.LrzXr.zdqRlf.kno-fv').textexcept:passtry:business_info['hours'] = driver.find_element(By.CSS_SELECTOR, 'div.VkpGBb span.OYb90e').textexcept:passtry:business_info['website'] = driver.find_element(By.CSS_SELECTOR, 'a.ab_button').get_attribute('href')except:pass# Google My Business情報の表示print("Google My Business Infoの情報です♪:")info_list = []for key, value in business_info.items():if value:info_list.append(f"{key.capitalize()}: {value}")print("\n".join(info_list))# 検索結果の情報を取得results = driver.find_elements(By.CSS_SELECTOR, 'div.g')print("\nGoogle Search Results(^^♪:")seen_links = set()for result in results:try:title = result.find_element(By.CSS_SELECTOR, 'h3').textlink = result.find_element(By.CSS_SELECTOR, 'a').get_attribute('href')snippet = result.find_element(By.CSS_SELECTOR, 'div.IsZvec').text# 重複するリンクを避けるif link in seen_links:continueseen_links.add(link)# Snippetを分割formatted_snippet = snippet.replace(' Map ', '\nMap\n').replace('. ', '.\n').replace(' 平日', '\n平日')print(f"Title: {title}\nLink: {link}\nSnippet:\n{formatted_snippet}\n")except:continue# ブラウザを閉じる#大事driver.quit()

3. 環境構築と準備

まず、スクレイピングを行うために必要なツールとライブラリをインストールします。

  1. VSCodeのインストール

    • VSCodeは、Python開発に非常に適したエディタです。全ての作業をPCで完結できるように、まずはVSCodeをインストールしましょう。

  2. Pythonファイルの実行

Pythonファイルをターミナルから実行するには、次のコマンドを使用します。
bash
コードをコピーする
py スペース ファイル名.py

必要なライブラリ等のインストール

Pandasなどのライブラリは、Pythonでデータ処理を行う際に非常に便利です。次のコマンドを使用してインストールします。

py -m pip install pandas

4. ダウンロードしたファイルの配置と実行


次に、ダウンロードしたプログラムを正しいフォルダに配置し、実行します。

  1. ファイルの配置

    • ダウンロードしたプログラムファイルは、デスクトップでは動作しないことがあるため、Pythonフォルダに移動しましょう。

  2. ファイルの実行

    • ファイルを実行して問題が発生した場合、多くはファイルパスやChromeDriverのバージョンの問題です。特に、ChromeDriverのバージョンがブラウザと一致していることを確認してください。

5. コードの編集と修正

コードを自分の環境に合わせて編集しましょう。

  1. サイトの決定

    • スクレイピングするサイトを決定し、そのURLをコードの28行目に貼り付けます。

  2. ページ訪問の設定

    • 51~80行目では、XPathを使用してページの特定要素を訪問するように設定します。XPathは、ブラウザの検証ツールを使って取得し、適切に配置します。

  3. データの抜き取り

    • 店名などのデータをXPathを使って抜き取ります。XPathが正しく設定されていることを確認し、必要に応じて調整します。

  4. コードの構成

    • 最後に、コード全体の構成を整え、効率的かつ読みやすくなるようにしましょう。特に、インデントやコメントを適切に配置して、後で見直しやすいようにします。

6. プログラムの実行とデバッグ


プログラムを実行し、必要に応じてデバッグを行います。

  1. プログラムの実行

    • 作成したコードを実行して、データが正しく取得できるか確認します。

  2. 問題解決

    • 問題が発生した場合は、コードの各部分を再確認し、適切な修正を行います。多くの場合、XPathの設定やChromeDriverのバージョンが原因で問題が発生します。トラブルを解決すると達成感があります、トラブル解決にむけて色々トライしていきましょう!別記事でトラブルシューティングのTipsをまとめていますので、よかったらチェックしてくださいね!

    • スクレイピングでデータが取得できるようになったら、クローラー開発のステップにいきましょう~

まとめ

今回の記事では、PythonとSeleniumを使用してWebスクレイピングを行い、データを効率的に取得する方法について解説しました。スクレイピングする際は、対象サイトの利用規約を必ず確認し、適切に行ってくださいね。

参考リンク

あなたのお役に立てば嬉しいです!一緒に頑張りましょうー

12【超初心者向け】PythonでWebスクレイピング:Seleniumを使ってデータを取得する方法~環境構築と全体の流れの説明~|友季子@Python学習中 (2024)
Top Articles
Nslij Ess Self Service
Methadone Clinic Leesburg Fl
Spasa Parish
Rentals for rent in Maastricht
159R Bus Schedule Pdf
Sallisaw Bin Store
Black Adam Showtimes Near Maya Cinemas Delano
Espn Transfer Portal Basketball
Pollen Levels Richmond
11 Best Sites Like The Chive For Funny Pictures and Memes
Things to do in Wichita Falls on weekends 12-15 September
Craigslist Pets Huntsville Alabama
Paulette Goddard | American Actress, Modern Times, Charlie Chaplin
Red Dead Redemption 2 Legendary Fish Locations Guide (“A Fisher of Fish”)
What's the Difference Between Halal and Haram Meat & Food?
R/Skinwalker
Rugged Gentleman Barber Shop Martinsburg Wv
Jennifer Lenzini Leaving Ktiv
Justified - Streams, Episodenguide und News zur Serie
Epay. Medstarhealth.org
Olde Kegg Bar & Grill Portage Menu
Cubilabras
Half Inning In Which The Home Team Bats Crossword
Amazing Lash Bay Colony
Juego Friv Poki
Dirt Devil Ud70181 Parts Diagram
Truist Bank Open Saturday
Water Leaks in Your Car When It Rains? Common Causes & Fixes
What’s Closing at Disney World? A Complete Guide
New from Simply So Good - Cherry Apricot Slab Pie
Drys Pharmacy
Ohio State Football Wiki
Find Words Containing Specific Letters | WordFinder®
FirstLight Power to Acquire Leading Canadian Renewable Operator and Developer Hydromega Services Inc. - FirstLight
Webmail.unt.edu
2024-25 ITH Season Preview: USC Trojans
Metro By T Mobile Sign In
Restored Republic December 1 2022
12 30 Pacific Time
Free Stuff Craigslist Roanoke Va
Wi Dept Of Regulation & Licensing
Pick N Pull Near Me [Locator Map + Guide + FAQ]
Crystal Westbrooks Nipple
Ice Hockey Dboard
Über 60 Prozent Rabatt auf E-Bikes: Aldi reduziert sämtliche Pedelecs stark im Preis - nur noch für kurze Zeit
Wie blocke ich einen Bot aus Boardman/USA - sellerforum.de
Infinity Pool Showtimes Near Maya Cinemas Bakersfield
Dermpathdiagnostics Com Pay Invoice
How To Use Price Chopper Points At Quiktrip
Maria Butina Bikini
Busted Newspaper Zapata Tx
Latest Posts
Article information

Author: Msgr. Refugio Daniel

Last Updated:

Views: 6027

Rating: 4.3 / 5 (74 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Msgr. Refugio Daniel

Birthday: 1999-09-15

Address: 8416 Beatty Center, Derekfort, VA 72092-0500

Phone: +6838967160603

Job: Mining Executive

Hobby: Woodworking, Knitting, Fishing, Coffee roasting, Kayaking, Horseback riding, Kite flying

Introduction: My name is Msgr. Refugio Daniel, I am a fine, precious, encouraging, calm, glamorous, vivacious, friendly person who loves writing and wants to share my knowledge and understanding with you.