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