मैं किसी पृष्ठ पर जावास्क्रिप्ट प्रस्तुत करने के लिए अनुरोध HTML का उपयोग कर रहा हूं। मैं प्रक्रिया को तेज करने के लिए concurrent.futures का भी उपयोग कर रहा हूं। मेरा कोड पूरी तरह से काम कर रहा था जब तक कि मैंने निम्नलिखित पंक्ति नहीं जोड़ी:

response.html.render(timeout=60, sleep=1, wait=3, retry=10)

जिस पर मुझे त्रुटि मिली:

response.html.render(timeout=60, sleep=1, wait=3, retries=10)   

फ़ाइल "C:\Users\Ze\Anaconda3\lib\site-packages\requests_html.py", लाइन 586, रेंडर में self.browser = self.session.browser # स्वचालित रूप से एक ईवेंट लूप और ब्राउज़र बनाएं
फ़ाइल "C:\Users\Ze\Anaconda3\lib\site-packages\requests_html.py", लाइन 727, ब्राउजर में self.loop = asyncio.get_event_loop()
फ़ाइल "C:\Users\Ze\Anaconda3\lib\asyncio\events.py", लाइन 639, में get_event_loop RuntimeError बढ़ाएँ ('थ्रेड% r में कोई वर्तमान ईवेंट लूप नहीं है।' RuntimeError: थ्रेड में कोई वर्तमान ईवेंट लूप नहीं है 'थ्रेडपूल एक्ज़ीक्यूटर-0_0'।

अगर मैं समस्याग्रस्त रेखा को नीचे के खंड में ले जाता हूं तो यह फिर से काम करता है, लेकिन फिर प्रतिपादन समानांतर में नहीं हो रहा है, है ना?

for result in concurrent.futures.as_completed(futures):
    result = result.result()

समस्या का कारण क्या है? मैंने कभी भी एसिंक्सियो का उपयोग नहीं किया है। क्या मुझे इसके लिए करना होगा? क्या इसे लागू करना आसान है?

आपका बहुत बहुत धन्यवाद!

कोड:

def load_page_and_extract_items(url):
    response = session.get(url, headers=get_headers())

    # render javascript
    response.html.render(timeout=60, wait=3)
    source = BeautifulSoup(response.html.raw_html, 'lxml')


def get_pages(remaining_urls):
    with concurrent.futures.ThreadPoolExecutor() as executor:
        # for each of 60 possible pages
        for current_page_number in range(60):
            futures = [executor.submit(load_page_and_extract_items, url) for url in remaining_urls]

            for result in concurrent.futures.as_completed(futures):
                result = result.result()

def main():
    get_pages(urls)
0
Python Millionaire 12 सितंबर 2021, 05:50
यहां कोई एसिंक्सियो नहीं है। हालांकि, मल्टीथ्रेडिंग है। load_page_and_extract_items स्पष्ट रूप से कुछ भी वापस नहीं करता है, इसलिए सुनिश्चित न करें कि आप परिणाम के साथ क्या करने की उम्मीद कर रहे हैं (जो कोई नहीं होगा)
 – 
BrutusForcus
12 सितंबर 2021, 09:52
उत्तर देने के लिए आपको बहुत बहुत धन्यवाद! कृपया मुझे क्षमा करें, मैंने निम्नलिखित कोड हटा दिया है क्योंकि इसका समस्या से कोई लेना-देना नहीं है क्योंकि यह कुछ पंक्तियों से पहले होता है। किसी कारण से मैं ThreadPoolExecutor से ProcessPoolExecutor में बदल गया और इसने पूरी तरह से काम किया, पता नहीं क्यों। Asyncio इस परिदृश्य में ProcessPoolExecutor के शीर्ष पर बहुत मददगार होगा, यह देखते हुए कि मैं पृष्ठों के लोड होने की प्रतीक्षा में बहुत समय बिताता हूं, है ना? यदि हां, तो मैं इसे कैसे कार्यान्वित कर सकता हूं?
 – 
Python Millionaire
12 सितंबर 2021, 10:01
यदि आप अपने अंतिम उद्देश्य की व्याख्या कर सकते हैं तो मुझे यकीन है कि आपको उचित सलाह मिलेगी। जैसा कि यह खड़ा है आपका कोड कुछ भी उपयोगी नहीं लगता है
 – 
BrutusForcus
12 सितंबर 2021, 10:17
कृपया मुझे क्षमा करें, मुझे नहीं लगा कि यह प्रासंगिक था। मैं बस अपने कोड को उसके महत्वपूर्ण तत्वों तक कम करने की कोशिश कर रहा था। लोड_पेज_और_एक्सट्रैक्ट_आइटम में पेज पूरी तरह से लोड होने के बाद, मैं एक निश्चित डिव निकालता हूं जिसमें वे सभी उत्पाद शामिल हैं जिन्हें मैं सुंदर सूप का उपयोग करके www.aliexpress.com पर ढूंढ रहा हूं और इसे अपने कंप्यूटर पर सहेजता हूं। मेरी पूरी परियोजना का वर्णन करने के लिए, मेरे पास 500 पृष्ठों की श्रेणियां हैं जिनमें से 60 पृष्ठों तक के उत्पाद हैं जिनमें मेरी रुचि है। मैं इसे पूरा करने का सबसे तेज़ तरीका ढूंढ रहा हूं। आपको क्या लगता है कि मुझे इसके बारे में कैसे जाना चाहिए?
 – 
Python Millionaire
12 सितंबर 2021, 10:29
मुझे संदेह है कि request.HTMLSession थ्रेड सुरक्षित नहीं है। आप AsyncHTMLSession का उपयोग करने पर विचार कर सकते हैं
 – 
BrutusForcus
12 सितंबर 2021, 10:59

1 उत्तर

सबसे बढ़िया उत्तर

यह सीधे सवाल का जवाब नहीं देता है लेकिन मल्टीथ्रेडेड वेब-स्क्रैपिंग के लिए एक तकनीक का प्रदर्शन करता है जो मेरे परीक्षणों में अच्छा प्रदर्शन करता है। यह मूल प्रश्न में बताए गए URL का उपयोग कर रहा है और कुछ ऐसे टैग की खोज करता है जिनमें HREF शामिल हैं और फिर उन URL को संसाधित करते हैं। सामान्य विचार यह है कि मैं सत्रों का एक पूल बनाता हूं और प्रत्येक थ्रेड को पूल (एक कतार) से सत्र ऑब्जेक्ट मिलता है, इसका उपयोग करता है और फिर इसे कतार में वापस रखता है जिससे यह अन्य धागे के लिए उपलब्ध हो जाता है।

from requests_html import HTMLSession
import concurrent.futures
import queue

QUEUE = queue.Queue()


def makeSessions(n=4):
    for _ in range(n):
        QUEUE.put(HTMLSession())


def cleanup():
    while True:
        try:
            getSession(False).close()
        except queue.Empty:
            break


def getSession(block=True):
    return QUEUE.get(block=block)


def freeSession(session):
    if isinstance(session, HTMLSession):
        QUEUE.put(session)


def getURLs():
    urls = []
    session = getSession()
    try:
        response = session.get('https://www.aliexpress.com')
        response.raise_for_status()
        response.html.render()
        for a in response.html.xpath('//dt[@class="cate-name"]/span/a'):
            if 'href' in a.attrs:
                urls.append(a.attrs['href'])
    finally:
        freeSession(session)
    return urls


def processURL(url):
    print(url)
    session = getSession()
    try:
        response = session.get(url)
        response.raise_for_status()
        response.html.render()
    finally:
        freeSession(session)


if __name__ == '__main__':
    try:
        makeSessions()
        with concurrent.futures.ThreadPoolExecutor() as executor:
            futures = [executor.submit(processURL, url) for url in getURLs()]
            for _ in concurrent.futures.as_completed(futures):
                pass
    finally:
        cleanup()
0
BrutusForcus 12 सितंबर 2021, 15:05
आपका बहुत बहुत धन्यवाद! यह बहुत उपयोगी होगा
 – 
Python Millionaire
14 सितंबर 2021, 07:56