私はPythonとSpark GraphXスキルを磨くために、ピンボードユーザーとブックマークのグラフを作成しようとしています。また、保存したすべてのユーザーを見つけ、ユーザーとのScrapeピンボードをScrapyで再帰的にスクラップ - 「スパイダーはリクエストを返す必要があります」エラー
- スタートし、すべてのブックマークurl_slugによって識別された各ブックマークの
- を、こすり:そうするためには、私は次の方法で再帰的にピンボードのブックマークをこすり同じブックマーク。ステップ2からユーザごとに
- は、プロセスを繰り返し、
私はこのロジックを実装しよう(ルールの使用を含む)ここでは、複数のスレッドから、試してみました提案を持つにもかかわらず(、... 1に進みます)私は強く私のコードでyield
/return
のこのミックスに関係している疑いがある
ERROR: Spider must return Request, BaseItem, dict or None, got 'generator'
:私は次のエラーを取得します。
ここ私のコードの簡単な説明:
私の主な解析方法は、(また、同じユーザのブックマークと以前のページ次)1人のユーザーのすべてのブックマークのアイテムを見つけては、これらのブックマークをこすりするparse_bookmark
方法を生み出します。
class PinSpider(scrapy.Spider):
name = 'pinboard'
# Before = datetime after 1970-01-01 in seconds, used to separate the bookmark pages of a user
def __init__(self, user='notiv', before='3000000000', *args, **kwargs):
super(PinSpider, self).__init__(*args, **kwargs)
self.start_urls = ['https://pinboard.in/u:%s/before:%s' % (user, before)]
self.before = before
def parse(self, response):
# fetches json representation of bookmarks instead of using css or xpath
bookmarks = re.findall('bmarks\[\d+\] = (\{.*?\});', response.body.decode('utf-8'), re.DOTALL | re.MULTILINE)
for b in bookmarks:
bookmark = json.loads(b)
yield self.parse_bookmark(bookmark)
# Get bookmarks in previous pages
previous_page = response.css('a#top_earlier::attr(href)').extract_first()
if previous_page:
previous_page = response.urljoin(previous_page)
yield scrapy.Request(previous_page, callback=self.parse)
この方法は、対応するurl_slug含む、ブックマークの情報を掻き取るPinscrapyItemに格納し、その後url_slugを解析するscrapy.Request
をもたらす:
def parse_bookmark(self, bookmark):
pin = PinscrapyItem()
pin['url_slug'] = bookmark['url_slug']
pin['title'] = bookmark['title']
pin['author'] = bookmark['author']
# IF I REMOVE THE FOLLOWING LINE THE PARSING OF ONE USER WORKS (STEP 1) BUT NO STEP 2 IS PERFORMED
yield scrapy.Request('https://pinboard.in/url:' + pin['url_slug'], callback=self.parse_url_slug)
return pin
最後parse_url_slug
方法は、他のユーザーを見つけこのブックマークを保存して再帰的にscrape.Request
を解析し、それぞれを解析します。
def parse_url_slug(self, response):
url_slug = UrlSlugItem()
if response.body:
soup = BeautifulSoup(response.body, 'html.parser')
users = soup.find_all("div", class_="bookmark")
user_list = [re.findall('/u:(.*)/t:', element.a['href'], re.DOTALL) for element in users]
user_list_flat = sum(user_list, []) # Change from list of lists to list
url_slug['user_list'] = user_list_flat
for user in user_list:
yield scrapy.Request('https://pinboard.in/u:%s/before:%s' % (user, self.before), callback=self.parse)
return url_slug
(私は他の興味深いフィールドを格納または重複などをチェックする場合、より簡潔な方法でコードを提示するために、私は部品を除去)
すべてのヘルプははるかに高く評価されるだろう!
コードが実行され、ありがとう!問題は、出力ファイルが空であることです。 [このSOの答え](https://stackoverflow.com/questions/17497640/python-scrapy-output-csv-file-empty)と[this one](https://stackoverflow.com/questions/31890731/scrapy-スクラップ - データ - 出力なし - ファイルへの出力)は、アイテムを返す必要があることを示しています。私は1つ、またはより正確には、2つのアイテム(PinscrapyItemとUrlSlugItem)を返すと考えました。何か不足していますか?私はパイプラインを使用していません。 – notiv
私は掻き削り自体が動作していることを忘れていました( 'ダウンローダ/レスポンスカウント:41) – notiv
@notiv、私の編集内容を参照してください –