2017-01-17 9 views
0

私はウェブサイトのscrapy "クリック"のリンクからテキストを収集したいと思います。 scrapyは、次のことを行っている。この場合、「クリックする」というリンクからテキストを収集していますか?

$ scrapy crawl dns_db 2>&1 | grep 'Parsing URL' 
2017-01-17 22:14:01 [dns_db] INFO: ## Parsing URL: http://www.iana.org/domains 
2017-01-17 22:14:02 [dns_db] INFO: ## Parsing URL: http://www.iana.org/domains/root 
2017-01-17 22:14:02 [dns_db] INFO: ## Parsing URL: http://www.iana.org/domains/root/db 

  1. オープン」www.iana.org

    # -*- coding: utf-8 -*- 
    import scrapy 
    from scrapy.linkextractors import LinkExtractor 
    from scrapy.spiders import CrawlSpider, Rule 
    
    
    class DnsDbSpider(CrawlSpider): 
        name = 'dns_db' 
        allowed_domains = ['www.iana.org'] 
        start_urls = ['http://www.iana.org/'] 
    
        rules = (
         Rule(LinkExtractor(
          allow_domains='www.iana.org', 
          restrict_css=r'#home-panel-domains > h2'), 
          callback='parse_item', 
          follow=True), 
         Rule(LinkExtractor(
          allow_domains='www.iana.org', 
          restrict_css=r'#main_right > p:nth-child(3)'), 
          callback='parse_item', 
          follow=True), 
         Rule(LinkExtractor(
          allow_domains='www.iana.org', 
          restrict_css=r'#main_right > ul:nth-child(4) > li'), 
          callback='parse_item', 
          follow=True), 
        ) 
    
    
        def parse_item(self, response): 
         self.logger.info('## Parsing URL: %s', response.url) 
         i = {} 
         return i 
    

    scrapyログ:

    は、次の例を考えてみましょう"
    path = []

  2. ドメイン名」のURLをクリックします。 "ドメイン名" ページをクリックし、 "DNSルートゾーン" URLで
    path = ['Domain Names']
  3. 。 "DNSルートゾーン" ページをクリックし、 "ルートゾーンデータベース" URLで
    path = ['Domain Names', 'The DNS Root Zone']

  4. path = ['Domain Names', 'The DNS Root Zone', 'Root Zone Database']
  5. ルートゾーンデータベース」のページでは、データをスクラップしてアイテムを作成します。
    path = ['Domain Names', 'The DNS Root Zone', 'Root Zone Database']

人間だけで、このパス/リストを見ることで、ウェブサイトに移動できます。最終的なアイテムもパス属性は持っているでしょう。

どうすれば実現できますか?あなたのURLテキストの上に運び、あなたが到達するまで、それをマージしておくことができます

$ scrapy crawl -L WARN dns_db 
2017-02-12 00:13:50 [dns_db] WARNING: ## Request path: [] 
2017-02-12 00:13:51 [dns_db] WARNING: ## Request path: [{'text': 'Domain Names', 'url': 'http://www.iana.org/domains'}] 
2017-02-12 00:13:51 [dns_db] WARNING: ## Request path: [{'text': 'Domain Names', 'url': 'http://www.iana.org/domains'}, {'text': 'The DNS Root Zone', 'url': 'http://www.iana.org/domains/root'}] 
2017-02-12 00:13:52 [dns_db] WARNING: ## Request path: [{'text': 'Domain Names', 'url': 'http://www.iana.org/domains'}, {'text': 'The DNS Root Zone', 'url': 'http://www.iana.org/domains/root'}, {'text': 'Root Zone Database', 'url': 'http://www.iana.org/domains/root/db/'}] 
+0

「ルートゾーンデータベース」のURLから始めないのはなぜですか?つまりhttp://www.iana.org/domains/root/db – Granitosaurus

+0

中間URLから一部のデータを削除する必要があります。この例では、 'nth-child(3)'、 'nth-child(4)'でフォローアップURLを検索する場所を限定しています。そうでなければ、サイト全体をクロールしました。 * iana.org *は例のウェブサイトですが、私の実際のターゲットは異なります。 –

答えて

0

# -*- coding: utf-8 -*- 
import scrapy 
from scrapy.linkextractors import LinkExtractor 


class DnsDbSpider(scrapy.Spider): 
    name = "dns_db" 
    allowed_domains = ["www.iana.org"] 
    start_urls = ['http://www.iana.org/'] 

    def parse(self, response): 
     if 'req_path' not in response.meta: 
      response.meta['req_path'] = [] 
     self.logger.warn('## Request path: %s', response.meta['req_path']) 
     restrict_css = (
      r'#home-panel-domains > h2', 
      r'#main_right > p:nth-child(3)', 
      r'#main_right > ul:nth-child(4) > li' 
     ) 
     links = [link for css in restrict_css for link in self.links(response, css)] 
     for link in links: 
      #self.logger.info('## Link: %s', link) 
      request = scrapy.Request(
       url=link.url, 
       callback=self.parse) 
      request.meta['req_path'] = response.meta['req_path'].copy() 
      request.meta['req_path'].append(dict(text=link.text, url=link.url)) 
      yield request 

    def links(self, response, restrict_css=None): 
     lex = LinkExtractor(
      allow_domains=self.allowed_domains, 
      restrict_css=restrict_css) 
     return lex.extract_links(response) 

コマンドライン出力:

EDIT

はここで働い例です必要なページをすべてマージしてください:

from scrapy import Spider, Request 

class MySpider(Spider): 
    name = 'iana' 
    start_urls = ['http://iana.org'] 
    link_extractors = [LinkExtract()] 

    def parse(self, response): 
     path = response.meta.get('path', []) # retrieve the path we have so far or set default 
     links = [l.extract_links(response) for l in self.link_extractors] 
     for l in links: 
      url = l.url 
      current_path = [l.text] 
      yield Request(url, self.parse, 
          meta={'path': path + current_path}) 
     # now when we reach the last page that we want, 
     # we return an item with all gathered path parts 
     last_page = True # some condition to determine that it's last page, e.g. no links found 
     if last_page: 
      item = dict() 
      item['path'] = ' > '.join(path) 
      # e.g. 'Domain Names > The DNS Root Zone > Root Zone Database' 
      return item 

このスパイダーは、何らかの条件が満たされたときにURLテキストを保存するたびにURLテキストを保存して、これまでに遭遇したすべてのパス値を持つアイテムを返します。

+0

これは私が求めていることではありません。私は、このパスを作成するためにクローラが必要なので、それが通過しているURLのテキストを収集します。最初はこのリストは空です。 –

+0

@NarūnasKとこのパスは何ですか?アイテム内のフィールドですか?私の例のように、Requestsメタパラメータに追加して検索するだけで、現在のURLまたは名前を持ち越すことができます。 – Granitosaurus

+0

私はちょうど質問を編集しました。一般的には、* path *は 'scrapy.Field()'である可能性があります。私はこの質問を作成しました。なぜなら、アイテムの寿命を理解していないからです。クローラーが「ドメイン名」にあるときにアイテムが作成された場合、クローラーが「ルートゾーンデータベース」に到達してもこのアイテムは有効ですか?このアイテムにアクセスするにはどうしたらいいですか? –

関連する問題