2017-12-08 3 views
0

(Very) Neu bei Python und Programmierung im AllgemeinenWie scrape mehrere Seiten von einer Website?

Ich habe versucht, die Daten von mehr Seiten zu kratzen/Schnitt der gleichen Website mit Scrapy

Mein Code funktioniert, aber es ist nicht lesbar und nicht praktisch

import scrapy 

class SomeSpider(scrapy.Spider): 
name = 'some' 
allowed_domains = ['https://example.com'] 
start_urls = [ 
'https://example.com/Python/?k=books&p=1', 
'https://example.com/Python/?k=books&p=2', 
'https://example.com/Python/?k=books&p=3', 
'https://example.com/Python/?k=tutorials&p=1', 
'https://example.com/Python/?k=tutorials&p=2', 
'https://example.com/Python/?k=tutorials&p=3', 
] 

def parse(self, response): 
response.selector.remove_namespaces() 

info1 = response.css("scrapedinfo1").extract() 
info2 = response.css("scrapedinfo2").extract() 

for item in zip(scrapedinfo1, scrapedinfo2): 
    scraped_info = { 
     'scrapedinfo1': item[0], 
     'scrapedinfo2': item[1]} 

     yield scraped_info 

Wie kann ich das verbessern?

Ich mag innerhalb einer bestimmten Menge von Kategorien suchen und Seiten

Ich brauche so etwas wie

categories = [books, tutorials, a, b, c, d, e, f] 
in a range(1,3) 

Damit Scrapy der Lage wäre, seine Arbeit durch alle Kategorien und Seiten zu tun, während dass sie leicht zu anderen Websites

Alle Ideen sind willkommen

Was ich habe versucht, bearbeiten und anpassen:

categories = ["books", "tutorials"] 
base = "https://example.com/Python/?k={category}&p={index}" 

def url_generator(): 
    for category, index in itertools.product(categories, range(1, 4)): 
     yield base.format(category=category, index=index) 

Aber Scrapy gibt

[scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), 
scraped 0 items (at 0 items/min) 
+0

Verwendung Taste '{}' richtig Code formatieren auf SO. – furas

+0

'url_generator()' ist eine Methode innerhalb der Klasse, also braucht es 'self' -' def url_generator (self): ', das selbe mit den Kategorien -' product (self.categories', ...). Übrigens: Verwenden Sie 'print()', um zu sehen, was Sie mit 'base.format (category = category, index = index)' erhalten. – furas

+0

scrapy hat Methode [start_requests] (https://doc.scrapy.org/en/latest/ topics/spiders.html # scrapy.spiders.Spider.start_requests) um URLs beim Start zu erzeugen. Und es muss 'Request (url = ...)' nicht nur String mit 'url' ergeben – furas

Antwort

0

Sie Methode können start_requests() Urls beim Start generieren yield Request(url) verwenden.

BTW: Später in parse() können Sie auch yield Request(url) verwenden, um neue URL hinzuzufügen.

Ich verwende das Portal toscrape.com, das zum Testen von Spinnen erstellt wurde.

import scrapy 

class MySpider(scrapy.Spider): 

    name = 'myspider' 

    allowed_domains = ['http://quotes.toqoute.com'] 

    #start_urls = [] 

    tags = ['love', 'inspirational', 'life', 'humor', 'books', 'reading'] 
    pages = 3 
    url_template = 'http://quotes.toscrape.com/tag/{}/page/{}' 

    def start_requests(self): 

     for tag in self.tags: 
      for page in range(self.pages): 
       url = self.url_template.format(tag, page) 
       yield scrapy.Request(url) 


    def parse(self, response): 
     # test if method was executed 
     print('url:', response.url) 

# --- run it without project --- 

from scrapy.crawler import CrawlerProcess 

#c = CrawlerProcess({ 
# 'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 
# 'FEED_FORMAT': 'csv', 
# 'FEED_URI': 'output.csv', 
#} 

c = CrawlerProcess() 
c.crawl(MySpider) 
c.start() 
1

Gelöst dank start_requests() und yield scrapy.Request()

Hier ist der Code

import scrapy 
import itertools 


class SomeSpider(scrapy.Spider): 
    name = 'somespider' 
    allowed_domains = ['example.com'] 

    def start_requests(self): 
     categories = ["books", "tutorials"] 
     base = "https://example.com/Python/?k={category}&p={index}" 

     for category, index in itertools.product(categories, range(1, 4)): 
      yield scrapy.Request(base.format(category=category, index=index)) 

    def parse(self, response): 
     response.selector.remove_namespaces() 

     info1 = response.css("scrapedinfo1").extract() 
     info2 = response.css("scrapedinfo2").extract() 

     for item in zip(info1, info2): 
      scraped_info = { 
       'scrapedinfo1': item[0], 
       'scrapedinfo2': item[1], 
      } 

      yield scraped_info 
+1

Sie sind richtig! Ich habe es ohne Doppelprüfung geschrieben! :) – Rawhide

+0

also entferne ich meinen vorherigen Kommentar :) – furas