我希望从两个网站获取信息并在实时'实时显示在控制台中。
要从网站获取信息,我使用的是BeautifulSoup 4.我读过,抓网站的瓶颈是连接或网站本身。所以我想使用多线程,因此可以同时完成读取操作。以下是我的代码:
import urllib
from bs4 import BeautifulSoup
import threading
import time
link_website_one = 'http://www.website1.com'
link_website_one = 'http://www.website2.com'
def request_url(url):
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'
header = { 'User-Agent' : user_agent }
req = urllib.request.Request(url, headers=header)
try:
response = urllib.request.urlopen(req)
return response
except urllib.error.HTTPError as e:
print('The server couldn\'t fulfill the request.')
print(e.code,': ', e.reason)
return None
except urllib.error.URLError as e:
print('We failed to reach a server.')
print(e.code,': ', e.reason)
return None
def new_entry(website, lis, arr, a_id):
if website == 0 :
info1 = arr.find()
info2 = arr.find('div', {'class' : '1'}).find('span', {'class' : '7'}).get_text().strip()
info3 = arr.find('span', {'class' : '2'}).get_text().strip()
info4 = arr.find('span', {'class' : '3'}).get_text().strip()
info5 = arr.find('span', {'class' : '4'}).get_text().strip()
info6 = arr.find('div', {'class' : '5'}).get_text().strip()
lis.append({'info1' : info1, 'info2' : info2, 'info3' : info3, 'info4' : info4, 'info5' : info5, 'info6' : info6})
elif website == 1 :
info1 = a_id
info2 = arr.find('span', {'class' : '8'}).get_text()
info3 = arr.find('div', {'class' : '9'}).get_text()
info4 = arr.find_all('div', {'class' : '10'})[0].get_text()
info5 = arr.find_all('div', {'class' : '10'})[1].get_text()
info6 = arr.a["href"]
lis.append({'info1' : info1, 'info2' : info2, 'info3' : info3, 'info4' : info4, 'info5' : info5, 'info6' : info6})
class AsyncSearch(threading.Thread):
def __init__(self, website, iter_rounds, delay_time):
threading.Thread.__init__(self)
self.website = website
self.iter_rounds = iter_rounds
self.delay_time = delay_time
def run(self):
if self.website == 0:
for z in range(self.iter_rounds):
req_1 = request_url(link_1)
content_1 =req_1.read()
soup_1 = BeautifulSoup(content_1, 'lxml')
arr_1 = soup_1.find_all('div', {'class' : 'special_class'})
for x in range(len(arr_1)):
id_as = int(arr_1[x].find('class123')['class2345'].split(',')[0].split('"')[3].strip())
if id_as not in found_ids_1:
found_ids_1.add(id_as)
new_entry(0, all_entries_1, arr_1[x], id_as)
#else:
# break
req_1.close()
time.sleep(self.delay_time)
elif self.website == 1:
for z in range(self.iter_rounds):
req_2 = request_url(link)
content_2 =req_2.read()
soup_2 = BeautifulSoup(content_2, 'lxml')
arr_2 = soup_2.find_all('div', {'class' : 'class445'})
for x in range(len(arr_2)):
if arr_2[x].a['oid'] not in found_ids_2:
#print('Mobile: ',test[x].a[Inserat_ID])
found_ids_2.add(arr_2[x].a['oid'])
new_entry(1, all_entries_1, arr_2[x], arr_2[x].a['oid'])
#else:
# break
req.close()
time.sleep(self.delay_time)
all_entries_1=[]
all_entries_2=[]
found_ids_1 = set()
found_ids_2 = set()
website1 = AsyncSearch(0,10,1)
website2 = AsyncSearch(1,10,1)
website1.start()
website2.start()
website1.join()
website2.join()
创建了两个列表中的第一个(all_entries 1/2)和两个集合(found_ids 1/2)。
我正在抓取的网站每页提供20个广告,其中包含独特的ID。使用new_entry方法,您可以说出您想要的网站,应该在哪个列表中附加新条目,哪个数组包含beautifulsoup以及要添加的广告的ID。
现在,对于mutlithreading,我创建了一个AsyncSearch类,您可以在其中选择网站,选择请求的迭代次数以及等待下一个请求的时间。
两套found_ids 1/2都在那里,所以你不要在all_entries列表中多次追加广告。
现在问题。这段代码有效。
但是:如果delay_time = 1且迭代次数= 10,则需要20秒才能完成。有没有更快的方法来解决这个问题?网站1的.read()持续时间介于0.12和0.17秒之间,网站2介于0.03和0.10秒之间。
如果我说任何不可理解的事情,请问。