ScrapyでCookieがどのように機能するか、およびそれらのCookieをどのように管理するかについて、少し混乱しています。
これは基本的に私がやろうとしていることの単純化されたバージョンです。
Webサイトにアクセスすると、セッションCookieが取得されます。
検索を行うと、Webサイトは検索内容を記憶するため、結果の次のページに移動するなどの操作を行うと、Webサイトは処理している検索を認識します。
私のクモはsearchpage_urlの開始URLを持っています
検索ページはparse()
によって要求され、検索フォームの応答はsearch_generator()
に渡されます
search_generator()
その後yield
s FormRequest
と検索フォームの応答を使用した多くの検索リクエスト。
これらのFormRequestsおよび後続の子リクエストのそれぞれは、独自のセッションを持つ必要があるため、独自の個別のcookiejarと独自のセッションCookieを持つ必要があります。
Cookieのマージを停止するメタオプションについて説明しているドキュメントのセクションを見てきました。それは実際にはどういう意味ですか?リクエストを行うクモは、それ以降の期間、独自のcookiejarを持つことになりますか?
CookieがSpiderごとのレベルにある場合、複数のSpiderが生成されるとどうなりますか?最初のリクエストジェネレーターのみが新しいスパイダーを生成し、それ以降はそのスパイダーのみが将来のリクエストを処理するようにすることは可能ですか?
複数の同時リクエストを無効にする必要があると仮定します..そうしないと、1つのスパイダーが同じセッションCookieで複数の検索を行い、今後のリクエストは行われた最新の検索にのみ関連しますか?
私は混乱しています、どんな説明も大いに受け取られるでしょう!
私が考えたもう1つのオプションは、セッションCookieを完全に手動で管理し、1つの要求から別の要求に渡すことです。
これは、Cookieを無効にしてから、検索応答からセッションCookieを取得し、それを後続の各リクエストに渡すことを意味すると思います。
これはあなたがこの状況ですべきことですか?
3年後、これはまさにあなたが探していたものだと思います: http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#std:reqmeta-cookiejar
スパイダーのstart_requestsメソッドで次のようなものを使用するだけです。
for i, url in enumerate(urls):
yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
callback=self.parse_page)
また、後続のリクエストでは、毎回明示的にcookiejarを再添付する必要があることに注意してください。
def parse_page(self, response):
# do some processing
return scrapy.Request("http://www.example.com/otherpage",
meta={'cookiejar': response.meta['cookiejar']},
callback=self.parse_other_page)
from scrapy.http.cookies import CookieJar
...
class Spider(BaseSpider):
def parse(self, response):
'''Parse category page, extract subcategories links.'''
hxs = HtmlXPathSelector(response)
subcategories = hxs.select(".../@href")
for subcategorySearchLink in subcategories:
subcategorySearchLink = urlparse.urljoin(response.url, subcategorySearchLink)
self.log('Found subcategory link: ' + subcategorySearchLink), log.DEBUG)
yield Request(subcategorySearchLink, callback = self.extractItemLinks,
meta = {'dont_merge_cookies': True})
'''Use dont_merge_cookies to force site generate new PHPSESSID cookie.
This is needed because the site uses sessions to remember the search parameters.'''
def extractItemLinks(self, response):
'''Extract item links from subcategory page and go to next page.'''
hxs = HtmlXPathSelector(response)
for itemLink in hxs.select(".../a/@href"):
itemLink = urlparse.urljoin(response.url, itemLink)
print 'Requesting item page %s' % itemLink
yield Request(...)
nextPageLink = self.getFirst(".../@href", hxs)
if nextPageLink:
nextPageLink = urlparse.urljoin(response.url, nextPageLink)
self.log('\nGoing to next search page: ' + nextPageLink + '\n', log.DEBUG)
cookieJar = response.meta.setdefault('cookie_jar', CookieJar())
cookieJar.extract_cookies(response, response.request)
request = Request(nextPageLink, callback = self.extractItemLinks,
meta = {'dont_merge_cookies': True, 'cookie_jar': cookieJar})
cookieJar.add_cookie_header(request) # apply Set-Cookie ourselves
yield request
else:
self.log('Whole subcategory scraped.', log.DEBUG)
ScrapyのCookie管理機能を再利用するために、検索クエリをスパイダー引数(コンストラクターで受け取る)として使用して、同じスパイダーの複数のインスタンスを実行するのが最も簡単なアプローチだと思います。したがって、複数のスパイダーインスタンスがあり、それぞれが特定の検索クエリとその結果をクロールします。しかし、あなたはクモを自分で走らせる必要があります:
scrapy crawl myspider -a search_query=something
または、Scrapydを使用して、JSON APIを介してすべてのスパイダーを実行できます。
def parse(self, response):
# do something
yield scrapy.Request(
url= "http://new-page-to-parse.com/page/4/",
cookies= {
'h0':'blah',
'taeyeon':'pretty'
},
callback= self.parse
)