pythonでwebアプリを作りながら勉強しているのですが、importの仕組みがよくわからないです。
importを使えば別の.pyの中にある変数も持ってこれるのでしょうか?
■検索エンジン
|---■config.py
|---■manage.py
|---■web_crawler
|---■\__init__.py
|---■crawler.py
|---■drop_collection.py
|---■search_engine
|---■\__init__.py
|---■template
|---■index.html
フォルダ構成はこのようになっていて
今はdrop_collection.pyを実行してDBのコレクションを削除したいのですが
エラー
from config import MONGO_URL
ImportError: No module named 'config'
表示されて実行出来ないです。
元々はcrawler.pyからimportしたCollectionを使って
Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test'), 'Index')
DBのコレクションを削除するプログラムだったんですけど、それが動かなくて自分で書き換えてみたのですが動きませんでした。
変更前drop_collection.pyの中身です。
# -*- coding: utf-8 -*-
__author__ = 'masashi'
#web_crawlerからDBのデータを持ってくるそしてcolの中にしまっとく。
from web_crawler import collection as col
def drop_collection():
col.drop()
if __name__ == '__main__':
drop_collection()
crawler.pyはしっかり動作するので
from config import MONGO_URL
を使ってDBのデータを持ってこれると思い以下のように書いたのですが同じエラーがでました。
pythonの対話から直接from config import MONGO_URLを行っても同じエラーが出たのでどうしていいかわかりません。
crawler.pyはmanage.pyを実行して動かすのですが、それと関係があるでしょうか?
検索エンジンのフォルダからpython対話に入ってfrom config import MONGO_URLを実行したらエラーが出ませんでした。
階層が関係あるみたいというのはわかりました。
ですが、プログラムをどのように書いたらいいのかわかりません。
詳しい方回答いただけないでしょうか?
変更後drop_collection.pyの中身です。
configのパスを変更したのですが新しいエラーが出てきました。
configが現在のディレクトリないのが問題だと返信を頂いたのですが、crawler.pyではconfigをうまく読み込めるます。それはどうしてなのでしょうか?
追記エラー
from ..config import MONGO_URL
SystemError: Parent module '' not loaded, cannot perform relative import
# -*- coding: utf-8 -*-
#これを直接実行するとDBの中身が削除される。
#help()でやると作った人の名前で出る。
__author__ = 'Wataru'
from urllib.parse import urlparse
from pymongo import MongoClient
from ..config import MONGO_URL
client = MongoClient(MONGO_URL)
db = client[urlparse(MONGO_URL).path[1:]]
col = db["Index"]
def drop_collection():
#作成したDBのコレクションを削除する。
col.drop()
#if__name__ == '__main__'はこれが直接実行されたものなのか(python drop_collection.py)チェックしてもしそうなら
#drop_collectionを実行する。
if __name__ == '__main__':
drop_collection()
config.pyの中身
import os
#接続先のホストはデフォルトだと ‘localhost’ でポート番号は 27017
# application settings
#os.environ.get('MONGO_URL')通常のサーバーにアプリをあげるならこのようにしてURLを持ってくる必要があると思う。
MONGO_URL = 'mongodb://localhost:27017/test'
# Generate a random secret key
SECRET_KEY = os.urandom(24)
#セキュリティについての設定だけどxssとcsrfというのがあるらしい(多分使われてないけど聞く必要がある)
#flaskのconfig設定だと思ったけど違った。
CSRF_ENABLED = True
crawler.pyの中身
# -*- coding: utf-8 -*-
#pythonの標準のモジュールでurlからhtmlのファイルを持って来てくれる。
import requests
#pythonの標準のモジュールでurlの解析をしてくれる。
from urllib.parse import urlparse
#mongodbを操作する時に使用するモジュールでMongoClientでDBに接続する。
from pymongo import MongoClient
#日本語形態のやつを解析できる。
from janome.tokenizer import Tokenizer
#htmlからリンクを抜き出してくれる。
from bs4 import BeautifulSoup
#config.pyからMONGO_URLを持ってくる。
from config import MONGO_URL
#DBに接続
#print(MONGO_URL) mongodb://localhost:27017/test
client = MongoClient(MONGO_URL)
#urlparseでURLのパスだけ抜き出す。それでデータベースを取得
#print(client) MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True)
#client[]はpythonの仕様じゃなくてpymongoの仕様、普通はclient.test_databaseでもいいけど'test-database'という
#風に使いたい場合は['test-database']と書くディクショナリ型を使う
db = client[urlparse(MONGO_URL).path[1:]] #.pathによって'/test'が抜き出されるそして[1:]によって前にある/が取り除かれる。
#dbに突っ込むと勝手にDatabase()が付くのも仕様
#print(db) Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test')
#存在するtestデータベースからIndexというコレクションを取り出す。
col = db["Index"]
#ここでコレクション"Index"を作っている。
#print(col) Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test'), 'Index')
def _split_to_word(text):
"""Japanese morphological analysis with janome.
Splitting text and creating words list.
"""
t = Tokenizer()
#token.surfaceで日本語の文字だけ取り出せる。例えば車は高いだったら"車" "は" "高い" だけ取り出せる。
return [token.surface for token in t.tokenize(text)]
def _get_page(url):
#r変数に<!DOCTYPE html>から代入する。
r = requests.get(url)
#レスポンスコードが200で正常だったら文字列""にして返す。
if r.status_code == 200:
return r.text
def _extract_url_links(html):
"""extract url links
>>> _extract_url_links('aa<a href="link1">link1</a>bb<a href="link2">link2</a>cc')
['link1', 'link2']
"""
#"html.parser"はなるべくpython標準のparserモジュールを使うように指定しているBeautifulSoup()で
#BeautifulSoupで扱えるようにしている。
soup = BeautifulSoup(html, "html.parser")
#aタグを全て持ってくる。
return soup.find_all('a')
def add_to_index(keyword, url):
#DBからキーワードが含まれたドキュメントを持ってくるentryに代入する
entry = col.find_one({'keyword': keyword})
if entry:
#entryの中にあるurlと引数のurlが同じじゃなければurlに引数のurlを追加して
if url not in entry['url']:
entry['url'].append(url)
#DBに保存する。saveは追加よりも更新って感じ
col.save(entry)
return
# not found, add new keyword to index
col.insert({'keyword': keyword, 'url': [url]})
def add_page_to_index(url, html):
body_soup = BeautifulSoup(html, "html.parser").find('body')
#htmlないの属性タグとその中身をchild_tagに入れていってる<body>以下にある全てのタグ<a>やら<th>やらを持ってくる。
#先ずはbodyより下のhtml全部持ってきて次にその下のdivを持ってきてul持ってきてどんどん掘り下げる感じ
for child_tag in body_soup.findChildren():
#beautifulsoupの機能でタグの名前だけ取り出してる。スクリプトだけは避ける。それ以降の処理がスキップされてループに戻る
if child_tag.name == 'script': #child_tag.nameタグの名前を取り出す
continue
#.textはそのタグの中身を表示する。<a>link</a>だったらlinkだけとりだす。
child_text = child_tag.text
for line in child_text.split('\n'): #文字列から改行を取り除いて分ける。
line = line.rstrip().lstrip() #上のコードだけだと両端の空白が消せないからここで削除している。実際には削除はできないので取り除いたのを返している
for word in _split_to_word(line): #janomaで日本語形態解析して単語をwordに代入
add_to_index(word, url)
def crawl_web(seed, max_depth):
to_crawl = {seed} #urlをto_crawlに入れて
crawled = []
next_depth = []
depth = 0
while to_crawl and depth <= max_depth:
#回収したurlの後ろを削除しpage_urlに入れる。
page_url = to_crawl.pop() #to_crawl(最初はurlが1つしか入らない)からurlを取り出して削除する
if page_url not in crawled:
html = _get_page(page_url)
add_page_to_index(page_url, html)
to_crawl = to_crawl.union(_extract_url_links(html)) #to_crawlに今まで入ってたurlとbf4で持ってきたurlを足してto_crawlに戻す最初0 + 5、4 + 2、5 + 0
crawled.append(page_url)
if not to_crawl:
to_crawl, next_depth = next_depth, [] #next_depthいる?
depth += 1