2017-12-19 8 views
0

Ich implementiere eine Datenpipeline für einen Chatbot. Ich crawle bestimmte Subreddits mit scrapy, um Submissions-IDs zu sammeln (nicht möglich mit praw - Python Reddit API Wrapper).Python: Scrapy und Reddit

Weiter benutze ich praw, um alle Kommentare recursevly zu erhalten. Beide Implementierungen funktionieren bereits.

ABER, Crawling subreddits wird von reddit nach ein paar Seiten verweigert (abhängig von der Geschwindigkeit der get Anfragen, ...).

Ich möchte keine Regeln brechen, aber gibt es eine richtige scrapy Konfiguration (DOWNLOAD_DELAY oder andere Drosselmechanismen), die innerhalb der reddit Regeln sind, um solche Informationen zu sammeln?

My Scrapy spider:

# -*- coding: utf-8 -*- 
import scrapy 

class RedditSpider(scrapy.Spider): 
    name = 'reddit' 
    allowed_domains = ["reddit.com"] 

    def __init__(self, subreddit=None, pages=None, *args, **kwargs): 
     super(RedditSpider, self).__init__(*args, **kwargs) 
     self.start_urls = ['https://www.reddit.com/r/%s/new/' % subreddit] 
     self.pages = int(pages) 
     self.page_count = 0 

    def parse(self, response): 

     # Extracting the content using css selectors 
     titles = response.css('.title.may-blank::text').extract() 
     # votes = response.css('.score.unvoted::text').extract() 
     # times = response.css('time::attr(title)').extract() 
     # comments = response.css('.comments::text').extract() 
     submission_id = response.css('.title.may-blank').xpath('@data-outbound-url').extract() 
     # submission_id = submission_id[24:33] 

     # Give the extracted content row wise 
     # for item in zip(titles, votes, times, comments, titles_full): 
     for item in zip(titles, submission_id): 
      # create a dictionary to store the scraped info 
      scraped_info = { 
       'title': item[0], 
       'submission_id': item[1][23:32] 
       # 'vote': item[2], 
       # 'created_at': item[3], 
       # 'comments': item[4] 
      } 

      # yield or give the scraped info to scrapy 
      yield scraped_info 

     if (self.pages > 1) and (self.page_count < self.pages): 
      self.page_count += 1 
      next_page = response.css('span.next-button a::attr(href)').extract_first() 
      if next_page is not None: 
       print("next page ... " + next_page) 
       yield response.follow(next_page, callback=self.parse) 

      if next_page is None: 
       print("no more pages ... lol") 

My spider Konfiguration:

# -*- coding: utf-8 -*- 

# Scrapy settings for reddit_crawler_scrapy project 
# 
# For simplicity, this file contains only settings considered important or 
# commonly used. You can find more settings consulting the documentation: 
# 
#  http://doc.scrapy.org/en/latest/topics/settings.html 
#  http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html 
#  http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html 

BOT_NAME = 'reddit_crawler_scrapy' 

SPIDER_MODULES = ['reddit_crawler_scrapy.spiders'] 
NEWSPIDER_MODULE = 'reddit_crawler_scrapy.spiders' 


# Crawl responsibly by identifying yourself (and your website) on the user-agent 
USER_AGENT = 'reddit_crawler_scrapy university project [email protected]' 

# Obey robots.txt rules 
ROBOTSTXT_OBEY = True 

# Configure maximum concurrent requests performed by Scrapy (default: 16) 
#CONCURRENT_REQUESTS = 32 

# Configure a delay for requests for the same website (default: 0) 
# See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay 
# See also autothrottle settings and docs 
DOWNLOAD_DELAY = 5 
# The download delay setting will honor only one of: 
#CONCURRENT_REQUESTS_PER_DOMAIN = 16 
#CONCURRENT_REQUESTS_PER_IP = 16 

# Disable cookies (enabled by default) 
#COOKIES_ENABLED = False 

# Disable Telnet Console (enabled by default) 
#TELNETCONSOLE_ENABLED = False 

# Override the default request headers: 
#DEFAULT_REQUEST_HEADERS = { 
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 
# 'Accept-Language': 'en', 
#} 

# Enable or disable spider middlewares 
# See http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html 
#SPIDER_MIDDLEWARES = { 
# 'reddit_crawler_scrapy.middlewares.RedditCrawlerScrapySpiderMiddleware': 543, 
#} 

# Enable or disable downloader middlewares 
# See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html 
#DOWNLOADER_MIDDLEWARES = { 
# 'reddit_crawler_scrapy.middlewares.MyCustomDownloaderMiddleware': 543, 
#} 

# Enable or disable extensions 
# See http://scrapy.readthedocs.org/en/latest/topics/extensions.html 
#EXTENSIONS = { 
# 'scrapy.extensions.telnet.TelnetConsole': None, 
#} 

# Configure item pipelines 
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html 
#ITEM_PIPELINES = { 
# 'reddit_crawler_scrapy.pipelines.RedditCrawlerScrapyPipeline': 300, 
#} 

# Enable and configure the AutoThrottle extension (disabled by default) 
# See http://doc.scrapy.org/en/latest/topics/autothrottle.html 
#AUTOTHROTTLE_ENABLED = True 
# The initial download delay 
#AUTOTHROTTLE_START_DELAY = 5 
# The maximum download delay to be set in case of high latencies 
#AUTOTHROTTLE_MAX_DELAY = 60 
# The average number of requests Scrapy should be sending in parallel to 
# each remote server 
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 
# Enable showing throttling stats for every response received: 
#AUTOTHROTTLE_DEBUG = False 

# Enable and configure HTTP caching (disabled by default) 
# See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings 
#HTTPCACHE_ENABLED = True 
#HTTPCACHE_EXPIRATION_SECS = 0 
#HTTPCACHE_DIR = 'httpcache' 
#HTTPCACHE_IGNORE_HTTP_CODES = [] 
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' 

#Export as CSV Feed 
FEED_FORMAT = "csv" 
FEED_URI = "reddit.csv" 


# RANDOMIZE_DOWNLOAD_DELAY = False 

LOG_FILE='scrapy_log.txt' 

I bereits gesetzt DOWNLOAD_DELAY bis 5 Sekunden, durch eine Zufallszahl multipliziert wird diese zwischen 0,5 und 1,5 von der Methode durch definierte RANDOMIZE_DOWNLOAD_DELAY. Das ist in einer get-Anfrage/Download etwas zwischen 2,5sec und 7,5sec, die bereits leise langsam ist, würde aber den Job über einige Stunden/Tage tun.

Noch zäh, nach ein paar Seiten bekomme ich keine nächste Seite, und die zuletzt aufgerufene Seite führt mich zu einem Beitrag von reddit mit einem Link, wie man Bots richtig einrichtet (imho im sarkastischen Ton - gut gespielter reddit) .

+0

Was fehlt in der API? – hansaplast

+0

Die API stellt nur Methoden bereit, um mehr oder weniger zufällige Subreddits oder sehr spezifische Abfragen zu erhalten. Es scheint viel mehr so, dass die Methoden für Anwendungen sind, die ein bestimmtes Thema präsentieren oder mit "populären" Subreddits oder Gold-Reddits usw. arbeiten: https://praw.readthedocs.io/en/latest/code_overview/reddit/subreddits. html –

Antwort

0

IMO arbeiten gegen reddits Anti-Crawl-Mechanismen kostet Sie zu viel Zeit, ich würde nicht versuchen, diesen Weg zu folgen.

Sie haben eine API, um alle Beiträge eines Subreddit, z. https://www.reddit.com/r/subreddit/top.json?sort=top bekommt alle Beiträge von in /r/subreddit als JSON-Format, es sieht aus wie der gleiche Inhalt wie Sie auf ihren Websites sehen.

Auch their doc vorschlagen, dass Sie oauth verwenden. Dann lassen Sie 60 Anfragen pro Minute erledigen. Ich würde stattdessen diese Straße gehen. Dies ist auch viel sicherer als das Scraping, da Scraping immer dann umkippt, wenn sie etwas in ihrem HTML-Layout ändern.

+0

https://www.reddit.com/r/subreddit/top.json?sort=top und Variationen davon erlaubt mir nicht, wie mehrere Seiten von Einreichungen innerhalb der/r/subreddit/new (alle Einreichungen beginnend mit die zuletzt eingereichten). Ich werde in die API-Dokumentation schauen, vielleicht finde ich etwas heraus. praw ist sogar in der offiziellen API-Dokumentation aufgeführt, bietet aber nicht die erforderlichen Methoden :( –

+0

Wenn jemand in der reddit-API-Dokumentation gut gelesen wird oder die Methoden kennt, die mir die angeforderten Daten zur Verfügung stellen, lassen Sie es mich wissen :) –

+0

haben Sie in https://www.reddit.com/r/subreddit/new.json?sort=new nachgesehen? – hansaplast