这是在Python中模拟刮取多个URL的正确方法吗?

这是在Python中模拟刮取多个URL的正确方法吗?,python,web-scraping,beautifulsoup,Python,Web Scraping,Beautifulsoup,我是Python新手,我正在创建一个用于抓取torrent站点的web刮板。为了获得磁石链接,我让它刮掉每一个torrent URL。问题是每次搜索都有大约20个链接需要抓取。这需要很长时间才能完成。因此,我使用numpy将URL刮取列表拆分为三个,并尝试使用线程同时刮取所有三个列表。看起来速度更快,但我不确定这是否是正确的方法。这是一次刮取多个URL的正确方法吗 谢谢 from bs4 import BeautifulSoup import re import np import pandas

我是Python新手,我正在创建一个用于抓取torrent站点的web刮板。为了获得磁石链接,我让它刮掉每一个torrent URL。问题是每次搜索都有大约20个链接需要抓取。这需要很长时间才能完成。因此,我使用numpy将URL刮取列表拆分为三个,并尝试使用线程同时刮取所有三个列表。看起来速度更快,但我不确定这是否是正确的方法。这是一次刮取多个URL的正确方法吗

谢谢

from bs4 import BeautifulSoup
import re
import np
import pandas as pd
import sys
import cfscrape
import threading
import os

scraper = cfscrape.create_scraper()

source=scraper.get("https://1337x.to/search/big+buck+bunny/1/").content
soup = BeautifulSoup(source, 'lxml')

tablebody = soup.find('tbody')

urllist=[]
filenamelist=[]
seederlist=[]
leecherlist=[]
sizelist=[]
datelist=[]
splitarr=[]
magnetlinks=[]
#split scraping process into three threads
def task1(): 
    for url1 in splitarr[0]:
        scrape_induvidual(url1)
def task2():
    for url2 in splitarr[1]:
        scrape_induvidual(url2)
def task3():
    for url3 in splitarr[2]:
        scrape_induvidual(url3)

#function for scraping induvidual urls in urllist
def scrape_induvidual(url):
    source = scraper.get(url).text
    soup=BeautifulSoup(source,'lxml')

    leftside=[]
    rightside=[]

    for h1_tag in soup.find('h1'):
        filenamelist.append(h1_tag)

    for ul_tag in soup.find_all('ul',{'class':'list'}):
        for li_tag in ul_tag.find_all('li'):
            for strong_tag in li_tag.find_all('strong'):
                leftside.append(strong_tag.text)
            for span_tag in li_tag.find_all('span'):
                rightside.append(span_tag.text)

    combined=(np.column_stack([leftside,rightside]))

    for each_detail in combined:
        if 'Seeders' in each_detail[0]:
            seederlist.append(each_detail[1])
        if 'Leechers' in each_detail[0]:
            leecherlist.append(each_detail[1])
        if 'Total size' in each_detail[0]:
            sizelist.append(each_detail[1])
        if 'Date uploaded' in each_detail[0]:
            datelist.append(each_detail[1])
    #get magnet link by looking for Magnet Download text and getting its parent anchor tag
    magnetlinks.append(soup.find(string="Magnet Download").find_parent('a').get('href'))

#extract page links for every torrent and store it in an array
for tag in tablebody.find_all('a'):
    temp_url=tag.get('href').split('/')
    if "torrent" in temp_url[1]:
      urllist.append('https://1337x.to'+(tag.get('href')))

#split array for parralel scraping
splitarr=np.array_split(urllist, 3)

t1 = threading.Thread(target=task1, name='t1') 
t2 = threading.Thread(target=task2, name='t2')   
t3 = threading.Thread(target=task3, name='t3')

t1.start() 
t2.start()
t3.start() 

t1.join()
t2.join()
t3.join()

combined=(np.column_stack([filenamelist,seederlist,leecherlist,sizelist,datelist,magnetlinks]))
df = pd.DataFrame(combined)
df.to_csv('test.csv', index=False)

您不需要也不需要线程,您可以使用而不是常规的cfscrap,然后使用asyncio在单个线程中并发处理请求


在Python中拥有更多的线程并不能真正提高这种用例的性能,尽管另一方面,您已经编写了代码,并且它似乎正在工作,所以这也很好。只是不要认为你从多个线程本身中得到了好处——你得到的好处是能够同时发出多个请求,通过在另一个线程运行时处理一个线程来隐藏一些延迟。

如果脚本工作正常,那么就可以了。在这种情况下,穿线是完全正常的。另一种方法是使用
asyncio
,但这在这里太过分了。那么,在我的例子中,发出多个请求的线程会提高速度吗?还是仅仅是安慰剂?是的,提出多个请求可以提高速度。想象一下,你想通过邮件与一个对手下100局国际象棋。如果你为所有100场比赛制定了第一步,并将其发送出去,然后在收到回复时回复,那么你将比每次只发送一步并等待回复更快地完成所有100场比赛。