前提・実現したいこと
データベースにリンクを格納する。そのため上記のエラーを解決したいです。
2018年に出版された本を元にコードを書いています。
recordsライブラリを使いsqliteのデータベースを管理、
そして乱数放送局をエミュレートしデータベースにランダムな番号の一覧と別のページへのリンクを格納しようとしています。
コードを全てミスがないか確認、理解して実行したのですがどうも思った様な結果が出ません。
実行後データベースを確認するとテーブルは作成されている様なのですが、そのテーブルの中にランダムな番号の一覧と別ページのリンクがありません。ターミナルよりエラーを確認した所この様なエラーが出ていたのでこれが原因でないかと推測しました。まだまだ勉強を始めたばかりでどうもわからないのですが、返答頂けるとありがたいです。
発生している問題・エラーメッセージ
Error closing cursor Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1324, in fetchone row = self._fetchone_impl() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1204, in _fetchone_impl return self.cursor.fetchone() sqlite3.ProgrammingError: Cannot operate on a closed database. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1339, in _safe_close_cursor cursor.close() sqlite3.ProgrammingError: Cannot operate on a closed database. Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1324, in fetchone row = self._fetchone_impl() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1204, in _fetchone_impl return self.cursor.fetchone() sqlite3.ProgrammingError: Cannot operate on a closed database. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "seven.py", line 113, in <module> url_to_visit = get_random_unvisited_page() File "seven.py", line 72, in get_random_unvisited_page link =db.query('''SELECT *FROM pages File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 214, in first record = self[0] File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 152, in __getitem__ next(self) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 136, in __next__ nextrow = next(self._rows) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 365, in <genexpr> row_gen = (Record(cursor.keys(), row) for row in cursor) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 999, in __iter__ row = self.fetchone() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1331, in fetchone self.connection._handle_dbapi_exception( File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1481, in _handle_dbapi_exception util.raise_( File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 178, in raise_ raise exception File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1324, in fetchone row = self._fetchone_impl() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1204, in _fetchone_impl return self.cursor.fetchone() sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) Cannot operate on a closed database. (Background on this error at: http://sqlalche.me/e/f405)
該当のソースコード
python
1import requests 2import records 3import re 4import os,os.path 5from bs4 import BeautifulSoup 6from urllib.parse import urljoin, urldefrag 7from sqlalchemy.exc import IntegrityError 8 9db =records.Database('sqlite:///wikipedia.db') 10 11db.query('''CREATE TABLE IF NOT EXISTS pages( 12 url text PRIMARY KEY, 13 created_at datetime, 14 html_file text Null, 15 visited_at datetime Null)''') 16 17db.query('''CREATE TABLE IF NOT EXISTS links( 18 url text,link_url text, 19 PRIMARY KEY (url,link_url))''') 20 21db.query('''CREATE TABLE IF NOT EXISTS images( 22 url text,img_url text,img_file text, 23 PRIMARY KEY (url,img_url))''') 24 25base_url = 'https://en.wikipedia.org/wiki/' 26file_store = './downloads/' 27 28if not os.path.exists(file_store): 29 os.makedirs(file_store) 30 31def url_to_file_name(url): 32 url = str(url).strip().replace('','') 33 return re.sub(r'(?u)[^-\w.]','',url) 34 35def download(url,filename): 36 r =requests.get(url,stream=True) 37 with open(os.path.join(file_store,filename),'wb') as the_image: 38 for byte_chunk in r.iter_content(chunk_size=4096*4): 39 the_image.write(byte_chunk) 40 41def store_page(url): 42 try: 43 db.query('''INSERT INTO pages (url,created_at) 44 VALUES(:url,CURRENT_TIMESTAMP)''', 45 url=url) 46 except IntegrityError as ie: 47 pass 48def store_link(url,link_url): 49 try: 50 db.query('''INSERT INTO links(url,link_url) 51 VALUES(:url,:link_url)''', 52 url=url,link_url=link_url) 53 except InergrityError as ie: 54 pass 55 56def store_image(url,img_url,img_file): 57 try: 58 db.query('''INSERT INTO images(url,img_url,img_file) 59 VALUES(:url,:img_url,:img_file)''', 60 url=url, img_url=img_url,img_file=img_file) 61 except IntegrityError as ie: 62 pass 63 64def set_visited(url,html_file): 65 db.query('''UPDATE pages 66 SET visited_at=CURRENT_TIMESTAMP, 67 html_file=:html_file 68 WHERE url=:url''', 69 url=url,html_file=html_file) 70 71def get_random_unvisited_page(): 72 link =db.query('''SELECT * FROM pages 73 WHERE visited_at Is NULL 74 ORDER BY RANDOM() LIMIT 1''').first() 75 return None if link is None else link.url 76 77def should_visit(link_url): 78 link_url = urldefrag(link_url)[0] 79 if not link_url.startswith(base_url): 80 return None 81 return link_url 82 83def visit(url): 84 print('Now visiting:',url) 85 html = requests.get(url).text 86 html_soup = BeautifulSoup(html,'html.parser') 87 88 for link in html_soup.find_all("a"): 89 link_url =link.get('href') 90 if link_url is None: 91 continue 92 link_url = urljoin(base_url, link_url) 93 store_link(url,link_url) 94 full_url=should_visit(link_url) 95 if full_url: 96 store_page(full_url) 97 for img in html_soup.find_all("img"): 98 img_url = img.get('src') 99 if img_url is None: 100 continue 101 img_url = urljoin(base_url,img_url) 102 filename = url_to_file_name(img_url) 103 download(img_url,filename) 104 store_image(url,img_url,filename) 105 106 filename = url_to_file_name(url) + 'html' 107 fullname = os.path.join(file_store,filename) 108 with open(fullname,'w','encoding=utf-8') as the_html: 109 the_html.write(html) 110 set_visited(url,filename) 111 112store_page(base_url) 113url_to_visit = get_random_unvisited_page() 114while url_to_visit is not None: 115 visit(url_to_visit) 116 url_to_visit = get_random_unvisited_page() 117
試したこと
エラーの内容をググリました。直訳ではdatabase、cursorが閉じているとのこと。
コードは合っている?と思ったので直接エラーを調べました。
結果海外のサイトでrecordsのバージョンを0.52にすることで解決しましたと見つけました。
バージョンが変わってしまうとどうしようもないのでしょうか?または、他に問題があるのでしょうか?
補足情報(FW/ツールのバージョンなど)
**records 0.5.3 **
beautifulsoup4 4.8.2
certifi 2019.11.28
chardet 3.0.4
docopt 0.6.2
et-xmlfile 1.0.1
idna 2.9
jdcal 1.4.1
openpyxl 2.4.11
pip 20.0.2
requests 2.23.0
selenium 3.141.0
setuptools 41.2.0
soupsieve 2.0
SQLAlchemy 1.3.15
tablib 1.1.0
urllib3 1.25.8
回答1件
あなたの回答
tips
プレビュー