PHPから来て、Pythonに新しくなりました。私はScrapyを使っていくつかのサイトを掻き集めて、チュートリアルと簡単なスクリプトをうまく使いたいと思っています。さて、実際の契約は、このエラーが来るの書き込み:1つの位置的な引数が欠けている、スキルの通過の応答
Traceback (most recent call last):
File "C:\Users\Naltroc\Miniconda3\lib\site-packages\twisted\internet\defer.py", line 653, in _runCallbacks current.result = callback(current.result, *args, **kw)
File "C:\Users\Naltroc\Documents\Python Scripts\tutorial\tutorial\spiders\quotes_spider.py", line 52, in parse self.dispatchersite
TypeError: thesaurus() missing 1 required positional argument: 'response'
Scrapyは自動的にシェルコマンドscrapy crawl words
が呼び出されるオブジェクトをインスタンス化します。
私が理解するところでは、self
はどのクラスメソッドの最初のパラメータです。クラスメソッドを呼び出すときには、引数としてself
を渡さず、代わりに変数を送信します。
は、まず、これが呼び出されます。PHPで
# Scrapy automatically provides `response` to `parse()` when coming from `start_requests()`
def parse(self, response):
site = response.meta['site']
#same as "site = thesaurus"
self.dispatcher[site](response)
#same as "self.dispatcher['thesaurus'](response)
その後、
def thesaurus(self, response):
filename = 'thesaurus.txt'
words = ''
ul = response.css('.relevancy-block ul')
for idx, u in enumerate(ul):
if idx == 1:
break;
words = u.css('.text::text').extract()
self.save_words(filename, words)
、これは$this->thesaurus($response)
を呼び出すのと同じでなければなりません。 parse
は明らかに変数としてresponse
を送信していますが、pythonには欠けていると言われています。 どこに行きましたか?ここ
全コード:
import scrapy
class WordSpider(scrapy.Spider):
def __init__(self, keyword = 'apprehensive'):
self.k = keyword
name = "words"
# Utilities
def make_csv(self, words):
csv = ''
for word in words:
csv += word + ','
return csv
def save_words(self, words, fp):
with ofpen(fp, 'w') as f:
f.seek(0)
f.truncate()
csv = self.make_csv(words)
f.write(csv)
# site specific parsers
def thesaurus(self, response):
filename = 'thesaurus.txt'
words = ''
print("in func self is defined as ", self)
ul = response.css('.relevancy-block ul')
for idx, u in enumerate(ul):
if idx == 1:
break;
words = u.css('.text::text').extract()
print("words is ", words)
self.save_words(filename, words)
def oxford(self):
filename = 'oxford.txt'
words = ''
def collins(self):
filename = 'collins.txt'
words = ''
# site/function mapping
dispatcher = {
'thesaurus': thesaurus,
'oxford': oxford,
'collins': collins,
}
def parse(self, response):
site = response.meta['site']
self.dispatcher[site](response)
def start_requests(self):
urls = {
'thesaurus': 'http://www.thesaurus.com/browse/%s?s=t' % self.k,
#'collins': 'https://www.collinsdictionary.com/dictionary/english-thesaurus/%s' % self.k,
#'oxford': 'https://en.oxforddictionaries.com/thesaurus/%s' % self.k,
}
for site, url in urls.items():
print(site, url)
yield scrapy.Request(url, meta={'site': site}, callback=self.parse)
おかげさまでありがとう。 1.引数として 'keyword'だけを常に取ることがわかっているなら、' __init__'に '** kwargs'を追加する理由はありますか? 2. 'parse'関数がコントローラとして機能するように見えます。まず、適切なパーサーを取得してデータを渡します。これは合理的ですが、 'response'データを送信する唯一の方法ですか? 3.なぜ 'getattr(self、response.meta ['site'])'を使用すると、 'self 'という接頭辞を付けずに適切なメソッドを呼び出すことができますか? – Naltroc
#1について。あなたはスパイダーから継承しているので、あなたは父親のクラスにkwargsを渡したいと思っていますが、ここでは何も渡す価値はありませんが、それはこの将来の証明になるパターンです。 2.あなたはscrapyの仕組みを誤解しています。デフォルトでは、スパイダーは 'start_urls'のすべてのurlと' parse() 'のデフォルトのコールバックを開始します。responseはstart_urlsのレスポンスオブジェクトです。あなたは自己が何であるかを誤解している。 'self'は現在のクラスオブジェクトへの参照です。したがって、' getattr'を使うときは、それが必要なわけではありません。 – Granitosaurus