Döngü ile Thread oluşturmak

Merhaba, localhost üzerinde kendi kodladığım sitemde denemeler yapıyorum. Yazdığım kod ile sayfadan belirli alanları çekiyorum. Program thread kullanmadan 40 saniye de çalışıyor, threading ile 10 saniye de. Süreden belirli ölçüde kar ettim fakat kodlar da göreceğiniz gibi thread yapısını tek tek yazdım bunun daha kolay yolunu beceremedim. En basit ve yalın şekilde düzenleyebilir misiniz?

import requests
from bs4 import BeautifulSoup
import threading


def craw(first, last):
for i in range(first, last):
    r = requests.get(f"http://127.0.0.1/sayfalar/{i}##")
    soup = BeautifulSoup(r.content, "lxml")
    for user in soup.find_all("myres", attrs={"class": "satirbasi"}):
        print(user.span.text)


t1 = threading.Thread(target=craw, args=(1, 100)).start()
t2 = threading.Thread(target=craw, args=(100, 200)).start()
t3 = threading.Thread(target=craw, args=(200, 300)).start()
t4 = threading.Thread(target=craw, args=(300, 400)).start()
t5 = threading.Thread(target=craw, args=(400, 500)).start()
t6 = threading.Thread(target=craw, args=(500, 600)).start()
t7 = threading.Thread(target=craw, args=(600, 700)).start()
t8 = threading.Thread(target=craw, args=(700, 800)).start()
t9 = threading.Thread(target=craw, args=(800, 900)).start()
t10 = threading.Thread(target=craw, args=(900, 1000)).start()

Şöyle bir döngü kullanılabilir:

import requests
from bs4 import BeautifulSoup
import threading
from math import ceil

def craw(first, range_):
    for i in range_:
        r = requests.get(f"http://127.0.0.1/sayfalar/{i}##")
        soup = BeautifulSoup(r.content, "lxml")
        for user in soup.find_all("myres", attrs={"class": "satirbasi"}):
            print(user.span.text)

def partition(iterable, step):
    i = 0
    while i < len(iterable):
        yield iterable[i:i+step]
        i += step

thread_count = 10
my_range = range(1, 1000)

for i in partition(my_range, ceil(len(my_range) / thread_count)):
    threading.Thread(target=craw, args=(i,)).start()

partition fonksiyonu kendisine verilen iterablestep uzunluğundaki parçalara ayırıyor, math.ceil de kendisine verilen sayıdan daha büyük olan en küçük tam sayıyı veriyor:

from math import ceil

assert ceil(1.2) == 2
assert ceil(3.9) == 4
assert ceil(6.45) == 7 

def partition(iterable, step):
    i = 0
    while i < len(iterable):
        yield iterable[i:i+step]
        i += step

assert list(partition([1, 2, 3, 4], 2)) == [[1, 2], [3, 4]]
assert list(partition((3, 4, 5, 2, 7), 2)) == [(3, 4), (5, 2), (7,)]
assert list(partition(range(10), 5)) == [range(0, 5), range(5, 10)]

thread_count = 10
my_range = range(1, 1000)

for i in partition(my_range, ceil(len(my_range) / thread_count)):
    print(i)

Daha az karmaşık olarak, mesela for döngüsü ile threadları daha az kod ile çalıştırmak mümkün değil mi hocam ?

Şöyle de yapılabilir:

import requests
from bs4 import BeautifulSoup
import threading

def craw(first, last):
    for i in range(first, last):
        r = requests.get(f"http://127.0.0.1/sayfalar/{i}##")
        soup = BeautifulSoup(r.content, "lxml")
        for user in soup.find_all("myres", attrs={"class": "satirbasi"}):
            print(user.span.text)

threading.Thread(target=craw, args=(1, 100)).start() # |1-100| = 99 ile diğerlerinden ayrıldığı için bir istisna
for i in range(100, 1000, 100):
    threading.Thread(target=craw, args=(i, i + 100)).start()

Hem temiz hem de daha anlaşılır oldu benim açımdan teşekkür ederim hocam

1 Beğeni