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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

Q&A

解決済

1回答

1424閲覧

rqでTypeErrorが出る

konataro

総合スコア37

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

0グッド

0クリップ

投稿2018/10/23 15:05

編集2018/10/24 11:32

redisを使ってクローラーとスクレイピング用の処理を分けています。

↓がクローラー側のソースコードです

Python

1import time 2import re 3 4import requests 5import lxml.html 6from redis import Redis 7from rq import Queue 8 9from mysql_test import MySQLQuery 10 11def main(): 12 """ 13 クローラーメイン処理 14 :return: 15 """ 16 17 q = Queue(connection=Redis) 18 db = MySQLQuery('ebook_htmls') 19 html_table = { 20 'urls': '', 21 'nums': '', 22 'htmls': '', 23 } 24 db.create_table(**html_table) 25 26 session = requests.Session() 27 response = session.get('https://gihyo.jp/dp') 28 urls = scrape_list_page(response) 29 for url in urls: 30 key = extract_key(url) 31 32 ebook_html = db.read(nums=str(key)) 33 if ebook_html is None: 34 time.sleep(1) 35 response = session.get(url) 36 37 html_table['urls'] = url 38 html_table['nums'] = key 39 html_table['htmls'] = response.content 40 41 q.enqueue('scraper_task.scrape', key, result_ttl=0) 42 43 db.close() 44 45 46 47def scrape_list_page(response): 48 """ 49 一覧ページのResponseから詳細ページのURLを抜き出す 50 :param response: 51 :return: 52 """ 53 root = lxml.html.fromstring(response.content) 54 root.make_links_absolute(response.url) 55 56 57 for a in root.cssselect('#listBook a[itemprop="url"]'): 58 url = a.get('href') 59 yield url 60 61def extract_key(url): 62 """ 63 URLからキーを抜き出す 64 :param url: 65 :return: 66 """ 67 68 m = re.search(r'/([^/]+)$', url) 69 return m.group(1) 70 71 72if __name__ == '__main__': 73 main()

これを実行すると↓のようにエラーがでます。

/tmp/pycharm_project_897/mysql_test.py:16: Warning: (1050, "Table 'ebook_htmls' already exists") self.cursor.execute('CREATE TABLE IF NOT EXISTS %s (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, %s)' % (self.table, key)) Traceback (most recent call last): File "/tmp/pycharm_project_897/crawl.py", line 73, in <module> main() File "/tmp/pycharm_project_897/crawl.py", line 41, in main q.enqueue('scraper_task.scrape', key, result_ttl=0) File "/home/tj/.conda/envs/menv_python3.6.6/lib/python3.6/site-packages/rq/queue.py", line 301, in enqueue job_id=job_id, at_front=at_front, meta=meta) File "/home/tj/.conda/envs/menv_python3.6.6/lib/python3.6/site-packages/rq/queue.py", line 253, in enqueue_call job = self.enqueue_job(job, at_front=at_front) File "/home/tj/.conda/envs/menv_python3.6.6/lib/python3.6/site-packages/rq/queue.py", line 308, in enqueue_job pipe = pipeline if pipeline is not None else self.connection._pipeline() TypeError: pipeline() missing 1 required positional argument: 'self'

エラーを出していると思われる場所enqueue_job関数内を見たのですが、さっぱりわかりません。@classmethodにして実行しましたが、エラーの出力は変わらず。

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

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

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

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

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

guest

回答1

0

ベストアンサー

self.connection._pipeline()で出ているエラーであり、self.connectionがインスタンス化されるべきところクラスのまま扱われているのだろうと推測できます。

これがどこからやってくるかと言うと、以下の行に起因します。

python

1 q = Queue(connection=Redis) 2

Redisはクラスなので、インスタンス化してあげてください。

参考:
rq – Pythonの単純ジョブキュー – GitHubじゃ!Pythonじゃ!
PythonでRedisを操作しよう (基本操作編)

投稿2018/10/23 15:33

hayataka2049

総合スコア30933

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

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

konataro

2018/10/23 15:46

回答ありがとうございます。おかげさまで、しっかりとプログラムが動きました。 インスタンス化について少しあやふやなのですが、 q = Queue(connection=Redis) のconnectionはクラスオブジェクトであり、 q = Queue(connection=Redis()) のconnectionはインスタンスオブジェクトということでしょうか。 また、Queueクラスの__init__(コンストラクタ?)でqのインスタンス変数connectionに上記のインスタンスオブジェクトを渡している、ということでいいんでしょうか。 def __init__(self, name='default', default_timeout=None, connection=None, async=True, job_class=None): self.connection = resolve_connection(connection) prefix = self.redis_queue_namespace_prefix self.name = name self._key = '{0}{1}'.format(prefix, name) self._default_timeout = parse_timeout(default_timeout) self._async = async # override class attribute job_class if one was passed if job_class is not None: if isinstance(job_class, string_types): job_class = import_attribute(job_class) self.job_class = job_class
hayataka2049

2018/10/23 15:49 編集

大筋はその理解で良いと思います。 self.connection = resolve_connection(connection) なので、インスタンス変数に入れる前に何かしら前処理をしているのかもしれませんが
konataro

2018/10/23 15:54

resolve_connectionの処理は呼び出すライブラリが多いため追えませんでしたが(諦めた)、何となく理解することができました。 ありがとうございますm(´_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問