🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python

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

pandas

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

Q&A

解決済

3回答

9179閲覧

pandasのdfを関数間で共有したい

george6493

総合スコア25

Python

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

pandas

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

0グッド

0クリップ

投稿2019/11/25 10:37

編集2019/11/27 05:43

#状況
pythonでpandasを使い、複数サイトでスクレイピングを行って、最終的にCSVを吐き出すプログラムを書いています。
まず、main.pyで以下のように関数の外でdfを宣言します。このdfは正常に作成されています。

columns = ["Name", "Price", "Url"] df = pd.DataFrame(columns=columns)

次に、一つ目の関数では、ECサイトの検索〜スクレイピングを行って、以下のような感じでdfに値を追加していきます。
nameは商品名、priceに値段、URLはその商品ページのURLです。

namepriceUrl
hogehogahogu
hugahogahuge

次の関数では、このdfからurlを取り出し、そのURLに飛んで、その商品のIDを取得した上で、このdfにIDの列とそれぞれの値を追加したいです。

|name |price |Url |ID|
|---|---|---|
|hoge |hoga |hogu |abc|
|huga |hoga |huge |def|

この後もIDを使ってさらに別サイトでスクレイピングしていきたいため、dfをグローバルで扱いたいと思っていますが、そもそも上にあげた二つの処理すらうまくいっていません。

Traceback

1Traceback (most recent call last): 2 File "main.py", line 14, in <module> 3 gethogeSearch.search_hoge(search_word, get_pages) 4 File "/hoge/gethogeSearch.py", line 102, in search_hoge 5 print(df) 6NameError: name 'df' is not defined

#(2019/11/27追記)試したこと
グローバル変数としてではなく、main.pyで指定した上で各モジュールには引数渡しをする

main

1import pandas as pd 2import gethogeSearch 3 4#各関数で共有するグローバル変数/最終成果物のcsvのモト 5columns = ["Name", "Price", "Url"] 6df = pd.DataFrame(columns=columns) 7 8#実行時にターミナルから叩く 9search_word = input('検索する語句:') 10number = input('ページ数:') 11get_pages = int(number) 12 13df = gethogeSearch.search_hoge(df, search_word, get_pages) 14 15print(df) 16

gethogesearch

1#coding UTF-8 2 3import requests 4from bs4 import BeautifulSoup 5import pandas as pd 6import csv 7from time import sleep 8import random 9import lxml.html 10 11def search_hoge(df, search_word, get_pages): 12 13 14 #検索ワードからスクレイピング対象URL(=url)生成(略) 15 16 page = 1 17 18 try: 19 #「get_pages」のページ分だけ繰り返す 20 while page < get_pages + 1: 21 22 #何ページ目を取得している最中なのか表示 23 print(page,"ページを取得中.....") 24 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36'} 25 26 #作成したURLからHTMLを取得 27 response = requests.get(url, headers=headers) 28 sleepTime = random.randint(2,8) 29 30 31 #BeautifulSoupの初期化 32 soup = BeautifulSoup(response.content, "lxml") 33 34 #検索結果リスト全体 35 items = soup.select(".hoge") 36 37 #リスト各要素に対して 38 for item in items: 39 name = item.find("span", {"class":"huga"}) 40 price = item.find("span", {"class":"hoge"}) 41 #空でないならdfに追加 42 if name != None and price != None: 43 nameTitle = name.string 44 priceText = price.string 45 item_url = item.a.get("href") 46 se = pd.Series([nameTitle, priceText, item_url], columns) 47 print(se) 48 df = df.append(se, columns) 49 50 #ページの下の方の「次のページ」のURLを取得 51 NextUrl = soup.find('li', {"class":"hg"}) 52 Url = NextUrl.a.get("href") 53 url = huga + Url 54 55 #次のページに行くので変数pageの値を1大きくする 56 page += 1 57 sleepTime = random.randint(3,15) 58 sleep(sleepTime) 59 except: 60 #取得しようと思ったページ数まで到達する前に終わったらそのページ以降はなかったと出力 61 nextpage = str(page+1) 62 print(nextpage + "以降のページはなかった") 63 64 finally: 65 #保存するcsvのファイル名を決める 66 filename = search_words + ".csv" 67 68 #作成したリストをcsvへ 69 df.to_csv(filename, encoding = 'utf-8-sig') 70 71 print("対象としたURL:" + url) 72 73 #終わったことを出力 74 print(filename + "を作成しました") 75 76 return df #empty dataframe

#教えていただきたいこと
なぜ引数渡しができていないのでしょうか。

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

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

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

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

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

tiitoi

2019/11/25 10:55

関数内で df が参照されるタイミングは df = pd.DataFrame(columns=columns) で df が定義されるよりあとのタイミングになっていますでしょうか?
hayataka2049

2019/11/25 12:18

コード全体、Traceback全文を含めたエラーメッセージの全体をご提示いただかないと回答はつきづらいと思います。
guest

回答3

0

グローバル変数とすれば各関数間で共有できますが、できないというのは何かが間違っているってことでしょう。

これ以上はコードの提示がないのでなんとも言えません

投稿2019/11/25 15:08

y_waiwai

総合スコア88038

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

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

george6493

2019/11/26 08:19

回答感謝いたします!先ほどmain.py全文を含め更新を行いましたので、確認いただけますでしょうか。
guest

0

モジュール(.pyファイル)をまたいでグローバル変数を使うことはできません。グローバル変数といえどスコープには制限があり、一つのファイルの中までです。

素直に引数と返り値で受け渡しするのが無難かと思います。渡すときは

python

1gethogeSearch.search_hoge(df, search_word, get_pages)

という感じですね。gethogeSearch.search_hoge側は相当する引数を受け取れるように書き換えます。また、DataFrameを書き換えて返したいのであれば最後にreturn文で返し、受け取る側で改めて変数dfに再代入します。

投稿2019/11/26 10:02

hayataka2049

総合スコア30935

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

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

george6493

2019/11/26 12:14 編集

ありがとうございます。グローバル変数のスコープの件、mainで呼んでいるから大丈夫なものと勘違いしておりました。ありがとうございます。 ところが、引数わたしにすると、受け取りをする関数内でdfを初期化しないと使えず(pandasに関係していることを書けないためでしょうか)、そのままの形で受け取れないようなのです。初期化せず受け取る手法がもしあればご教示いただけますと幸いです。
hayataka2049

2019/11/26 13:41

呼び出し側と関数定義、発生している問題の記述を追記してみてもらえますか?
george6493

2019/11/27 05:29

呼び出し側と定義側を全文追記いたしました。また返り値とmainのdfのprintの結果をコメントで併記しております。 お手数おかけしてごめんなさい。ここまでも、ご教示いただきありがとうございます!
guest

0

自己解決

hayatakaさま、誤解を生みまして失礼いたしました。
規約違反等ないサイトに限って運用させていただきます。

こちらのリンクの
https://qiita.com/567000/items/d8a29bb7404f68d90dd4
「型(カラム)だけ決まっているDataFarmeに値(行)を追加していく」
を参考に関数内での追記処理をしたところうまくいきました。

投稿2019/11/27 07:29

george6493

総合スコア25

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問