2015-09-22 9 views
6

के लिए एक रीस्टफुल फ्लास्क एपीआई बनाना एपीआई को मनमाने ढंग से HTTP को यूआरएल युक्त अनुरोध प्राप्त करने की अनुमति देनी चाहिए, जिसे उपयोगकर्ता स्क्रैप करना चाहता है, और फिर फ्लास्क को स्क्रैप के परिणाम वापस करना चाहिए।स्केपर

निम्न कोड पहले http अनुरोध के लिए काम करता है, लेकिन ट्विस्ट रिएक्टर बंद होने के बाद, यह पुनरारंभ नहीं होगा। मैं इस बारे में सही तरीके से भी नहीं जा रहा हूं, लेकिन मैं सिर्फ हेरोोकू पर एक रीस्टफुल स्केपर एपीआई रखना चाहता हूं, और जो कुछ भी मेरे पास है, वह सब मैं सोच सकता हूं।

क्या इस समाधान को आर्किटेक्ट करने का कोई बेहतर तरीका है? या मैं scrape_it को मुड़ने वाले रिएक्टर को रोकने के बिना वापस लौटने की अनुमति कैसे दे सकता हूं (जिसे फिर से शुरू नहीं किया जा सकता है)?

from flask import Flask 
import os 
import sys 
import json 

from n_grams.spiders.n_gram_spider import NGramsSpider 

# scrapy api 
from twisted.internet import reactor 
import scrapy 
from scrapy.crawler import CrawlerRunner 
from scrapy.xlib.pydispatch import dispatcher 
from scrapy import signals 

app = Flask(__name__) 


def scrape_it(url): 
    items = [] 
    def add_item(item): 
     items.append(item) 

    runner = CrawlerRunner() 

    d = runner.crawl(NGramsSpider, [url]) 
    d.addBoth(lambda _: reactor.stop()) # <<< TROUBLES HERE ??? 

    dispatcher.connect(add_item, signal=signals.item_passed) 

    reactor.run(installSignalHandlers=0) # the script will block here until the crawling is finished 


    return items 

@app.route('/scrape/<path:url>') 
def scrape(url): 

    ret = scrape_it(url) 

    return json.dumps(ret, ensure_ascii=False, encoding='utf8') 


if __name__ == '__main__': 
    PORT = os.environ['PORT'] if 'PORT' in os.environ else 8080 

    app.run(debug=True, host='0.0.0.0', port=int(PORT)) 
+0

क्या आप एक ट्रेसबैक त्रुटि या कुछ भी प्रदान कर सकते हैं? इसके अलावा, इस लाइन को 'd.addboth (lambda _: reactor.stop()) को हटाएं और 'reactor.run()' के बाद रिएक्टर.स्टॉप को कॉल करें, मैं इसे त्रुटियों में डाल रहा हूं क्योंकि जब यह प्रवेश करता है फ़ंक्शन रिएक्टर प्रारंभिक स्थिति या बंद राज्य में हो सकता है। इसकी गारंटी नहीं है। – AdriVelaz

+0

आप स्केपर का उपयोग क्यों करना चाहते हैं? पृष्ठों को स्क्रैप करने के अन्य तरीके – ahmed

+0

@ahmed मेरी समस्या कई पृष्ठों को खींचने के लिए एक एसिंच कतार का निर्माण कर रही है, और फिर उन पृष्ठों पर लिंक पर जा रही है। इसके लिए आप क्या सलाह देंगे? –

उत्तर

16

मुझे लगता है कि स्केपर के लिए फ्लास्क-आधारित API बनाने का कोई अच्छा तरीका नहीं है। फ्लास्क इसके लिए एक सही उपकरण नहीं है क्योंकि यह इवेंट लूप पर आधारित नहीं है। चीजों को और खराब करने के लिए, ट्विस्ट रिएक्टर (जो स्केपर का उपयोग करता है) can't एक थ्रेड में एक से अधिक बार शुरू/बंद कर दिया जाना चाहिए।

मान लें कि ट्विस्ट रिएक्टर के साथ कोई समस्या नहीं है और आप इसे शुरू और रोक सकते हैं। यह चीजों को बेहतर नहीं बनायेगा क्योंकि आपका scrape_it फ़ंक्शन एक विस्तृत अवधि के लिए अवरुद्ध हो सकता है, और इसलिए आपको कई थ्रेड/प्रक्रियाओं की आवश्यकता होगी।

मुझे लगता है कि जाने का तरीका एपीआईसी फ्रेमवर्क जैसे ट्विस्ट या टॉरनाडो का उपयोग करके एपीआई बनाना है; यह फ्लास्क-आधारित (या Django- आधारित) समाधान से अधिक कुशल होगा क्योंकि एपीआई स्पाइडर चलाने के दौरान अनुरोधों को पूरा करने में सक्षम होगा।

स्क्रैप ट्विस्ट पर आधारित है, इसलिए twisted.web या https://github.com/twisted/klein का उपयोग करके अधिक सरल हो सकता है। लेकिन टोरनाडो भी मुश्किल नहीं है क्योंकि आप इसे ट्विस्टेड इवेंट लूप का उपयोग कर सकते हैं।

ScrapyRT नामक एक प्रोजेक्ट है जो कि आप जो कार्यान्वित करना चाहते हैं उसके समान कुछ करता है - यह स्केपर के लिए एक HTTP API है। ScrapyRT ट्विस्ट पर आधारित है।

स्केपर-टोरनाडो एकीकरण जांच की जांच के रूप में Arachnado - here टोरनाडो के आवेदन के साथ स्केपर के क्रॉलर प्रोसेस को एकीकृत करने के तरीके पर एक उदाहरण है।

यदि आप वास्तव में फ्लास्क-आधारित एपीआई चाहते हैं तो यह अलग प्रक्रियाओं में क्रॉल शुरू करने और/या सेलेरी जैसे कतार समाधान का उपयोग करने के लिए समझ में आ सकता है। इस तरह आप अधिकांश स्केपर दक्षता खो रहे हैं; यदि आप इस तरह से जाते हैं तो आप अनुरोध + सुंदर सूप का भी उपयोग कर सकते हैं।

3

मैं ऐसी ही परियोजना पिछले सप्ताह पर काम कर रहा है, यह एसईओ सेवा एपीआई, मेरे कार्यप्रवाह इस ऐसा हुआ करता था:

  • ग्राहक एक URRL साथ कुप्पी आधारित सर्वर के लिए एक अनुरोध भेजने के स्क्रैप करने का, और एक कॉलबैक स्क्रैपिंग होने पर क्लाइंट को सूचित करने के लिए यूआरएल (क्लाइंट यहां एक अन्य वेब ऐप है)
  • python-daemon का उपयोग करके पृष्ठभूमि में रन स्केपर चलाएं। मकड़ी डेटा को डेटाबेस में सहेज लेगा।
  • बैकगाउंड सेवा स्पाइडर होने पर कॉलबैक यूआरएल को कॉल करके ग्राहक को सूचित करेगी।
+0

क्या आप कॉलबैक यूआरएल विचार को समझने में मेरी मदद कर सकते हैं? मैं उस बिंदु तक आपका अनुसरण करता हूं, और मुझे यकीन नहीं है कि इसे कैसे कार्यान्वित किया जाए ... धन्यवाद btw, यह एक शानदार विचार है –

+0

क्रॉलर समाप्त हो गया है तो यह आपके ग्राहक को पता चलेगा। यह केवल तभी उपयोगी होता है जब आपका ग्राहक एक वेबसाइट हो। यदि आप कॉलबैक का उपयोग नहीं करते हैं, तो आपका ग्राहक समय-समय पर जांच करेगा कि क्रॉलर समाप्त हो गया है या नहीं। – ahmed

संबंधित मुद्दे