2017-05-25 3 views
0

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) 

答えて

2

小さなerorrsの多くは、すべてのコードの周りにあります。私は普通のpython/scrapyの慣用句に従うためにそれを少しきれいにする自由を取った:)

+0

おかげさまでありがとう。 1.引数として 'keyword'だけを常に取ることがわかっているなら、' __init__'に '** kwargs'を追加する理由はありますか? 2. 'parse'関数がコントローラとして機能するように見えます。まず、適切なパーサーを取得してデータを渡します。これは合理的ですが、 'response'データを送信する唯一の方法ですか? 3.なぜ 'getattr(self、response.meta ['site'])'を使用すると、 'self 'という接頭辞を付けずに適切なメソッドを呼び出すことができますか? – Naltroc

+1

#1について。あなたはスパイダーから継承しているので、あなたは父親のクラスにkwargsを渡したいと思っていますが、ここでは何も渡す価値はありませんが、それはこの将来の証明になるパターンです。 2.あなたはscrapyの仕組みを誤解しています。デフォルトでは、スパイダーは 'start_urls'のすべてのurlと' parse() 'のデフォルトのコールバックを開始します。responseはstart_urlsのレスポンスオブジェクトです。あなたは自己が何であるかを誤解している。 'self'は現在のクラスオブジェクトへの参照です。したがって、' getattr'を使うときは、それが必要なわけではありません。 – Granitosaurus

関連する問題