質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

1回答

1060閲覧

スクレイピングした結果をcsvデータで保存する方法について

kakugen

総合スコア3

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2021/05/21 04:38

昨年、こちらのサイトでスクレイピングしたものをレビューしてもらったのですが、その先の工程として、スクレイピングしたものをcsvに落とし込む方法がわかりません。
恐縮ですが、アドバイスいただけますでしょうか?よろしくお願いいたします。

import re import time from urllib.parse import urljoin from bs4 import BeautifulSoup import requests # 予め正規表現でそれぞれのパターンを準備しておく 郵便番号パターン = r'〒\d{3}-\d{4}' 電話番号パターン = r'TEL : \d{2,4}?-\d{2,4}?-\d{3,4}' # 今回のケースの場合56行目で相対パスとして取得される為、予めここでもウェブサイトURL部分と分割しておく url = 'http://kensaku.shiho-shoshi.or.jp' href = '/search/member.php?search_code=01&search_name=&search_address=&x=140&y=16&pageID=1' while True: html = requests.get(urljoin(url, href)) # urljoinでURLの結合 soup = BeautifulSoup(html.content, 'html.parser') # table要素を指定 table = soup.find('table', id='kojin') # table内から全てのtr要素を取得 tr_list = soup.find_all('tr') for tr in tr_list: # table要素内にtacクラスの要素がある場合に実行(要は1番目のtr要素の除外) if tr.find_all(class_='tac'): # 大まかにtr要素内の全ての文字列を取得・分割しておく td_list = [td.text for td in tr.find_all('td')] # 氏名を漢字表記とルビ表記で分割 # 氏名欄にimg要素が含まれていた場合には名前の先頭に目印として○をつける if tr.find('img'): names = td_list[1].split('\n') names[0] = '○' + names[0] else: names = td_list[1].split('\n') # 正規表現のパターンが一致した場合に郵便番号の取得 zipcode = re.search(郵便番号パターン, td_list[4]).group() # 正規表現のパターンが一致した場合に電話番号の取得 # (電話番号を載せていないケースもある為try文を使用する) try: telephone = re.search(電話番号パターン, td_list[4]).group() locate = td_list[4].replace('\t','').replace('\n', '').replace(zipcode, '').replace(telephone, '') # 電話番号を掲載していなかった場合の処理 except: telephone = 'NO TEL' locate = td_list[4].replace('\t','').replace('\n', '').replace(zipcode, '') print('電話番号:', telephone) print('郵便番号:', zipcode) print('住所:', locate) print('氏名:', names) print('='*20) print('='*50) # ページ内に[次のページ]を表す[>]が存在するかを判定 # 存在した場合Trueが返ってくる為、if文が実行される(hrefの値が更新され次のページにループする) if soup.find(class_='pagebottom').find_all('a', attrs={'title':'next page'}): # 取得したhrefは相対パスである為、16行目でウェブサイトURLと結合される href = soup.find(class_='pagebottom').find('a', attrs={'title':'next page'}).get('href') # 次のページが存在しなかった場合にはループが終了 else: break # 短時間に連続してリクエストを送る行為はマナー違反且つサーバーへの負荷となる為 # 標準ライブラリよりtimeモジュールを使用して1秒間隔でリクエストを送る様に調整 time.sleep(1)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

問題文読ませていただきました。

こんな感じでしょうか?追記の部分をご確認ください。

Python

1import re 2import time 3from urllib.parse import urljoin 4from bs4 import BeautifulSoup 5import requests 6# 追記 7import csv 8 9# 予め正規表現でそれぞれのパターンを準備しておく 10郵便番号パターン = r'〒\d{3}-\d{4}' 11電話番号パターン = r'TEL : \d{2,4}?-\d{2,4}?-\d{3,4}' 12# 今回のケースの場合56行目で相対パスとして取得される為、予めここでもウェブサイトURL部分と分割しておく 13url = 'http://kensaku.shiho-shoshi.or.jp' 14href = '/search/member.php?search_code=01&search_name=&search_address=&x=140&y=16&pageID=1' 15 16# 追記 17output = [['電話番号', '郵便番号', '住所', '氏名', 'ふりがな']] 18 19while True: 20 html = requests.get(urljoin(url, href)) # urljoinでURLの結合 21 soup = BeautifulSoup(html.content, 'html.parser') 22 # table要素を指定 23 table = soup.find('table', id='kojin') 24 # table内から全てのtr要素を取得 25 tr_list = soup.find_all('tr') 26 for tr in tr_list: 27 # table要素内にtacクラスの要素がある場合に実行(要は1番目のtr要素の除外) 28 if tr.find_all(class_='tac'): 29 # 大まかにtr要素内の全ての文字列を取得・分割しておく 30 td_list = [td.text for td in tr.find_all('td')] 31 # 氏名を漢字表記とルビ表記で分割 32 # 氏名欄にimg要素が含まれていた場合には名前の先頭に目印として○をつける 33 if tr.find('img'): 34 names = td_list[1].split('\n') 35 names[0] = '○' + names[0] 36 else: 37 names = td_list[1].split('\n') 38 # 正規表現のパターンが一致した場合に郵便番号の取得 39 zipcode = re.search(郵便番号パターン, td_list[4]).group() 40 # 正規表現のパターンが一致した場合に電話番号の取得 41 # (電話番号を載せていないケースもある為try文を使用する) 42 try: 43 telephone = re.search(電話番号パターン, td_list[4]).group() 44 locate = td_list[4].replace('\t', '').replace( 45 '\n', '').replace(zipcode, '').replace(telephone, '') 46 # 電話番号を掲載していなかった場合の処理 47 except: 48 telephone = 'NO TEL' 49 locate = td_list[4].replace('\t', '').replace( 50 '\n', '').replace(zipcode, '') 51 52 # 追記 53 output.append([telephone, zipcode, locate, names[0], names[1]]) 54 # ページ内に[次のページ]を表す[>]が存在するかを判定 55 # 存在した場合Trueが返ってくる為、if文が実行される(hrefの値が更新され次のページにループする) 56 if soup.find(class_='pagebottom').find_all('a', attrs={'title': 'next page'}): 57 # 取得したhrefは相対パスである為、16行目でウェブサイトURLと結合される 58 href = soup.find(class_='pagebottom').find( 59 'a', attrs={'title': 'next page'}).get('href') 60 # 次のページが存在しなかった場合にはループが終了 61 else: 62 break 63 # 短時間に連続してリクエストを送る行為はマナー違反且つサーバーへの負荷となる為 64 # 標準ライブラリよりtimeモジュールを使用して1秒間隔でリクエストを送る様に調整 65 time.sleep(1) 66 67# 追記 68with open('./data.csv', 'w') as file: 69 writer = csv.writer(file, lineterminator='\n') 70 writer.writerows(output)

ご確認のほど、よろしくお願いいたします。????‍♂️

投稿2021/05/21 05:34

編集2021/05/21 05:35
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kakugen

2021/05/21 06:51

取得できました!ありがとうございます。
退会済みユーザー

退会済みユーザー

2021/05/21 07:05

お、ナイストライです。 また何か困ったことがありましたら、気軽にご相談ください〜!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問