该网站有六个主要产品类别。属于子类别的产品也可以在主类别中找到(例如/furniture/furniture/tables中的产品也可以在/furniture中找到),因此您只需从主类别中收集产品。您可以从主页获取类别链接,但使用站点地图会更容易。
url = 'https://www.courts.com.sg/sitemap/'
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
cats = soup.select('li.level-0.category > a')[:6]
links = [i['href'] for i in cats]
正如您所提到的,有些链接具有不同的结构,例如:/televisions。但是,如果您单击该页面上的View All Products 链接,您将被重定向到/tv-entertainment/vision/television。因此,您可以从/tv-entertainment 获得所有/televisions rpoducts。同样,品牌链接中的产品可以在主要类别中找到。例如,/asus 产品可以在/computing-mobile 和其他类别中找到。
下面的代码收集了所有主要类别的产品,因此它应该收集网站上的所有产品。
from bs4 import BeautifulSoup
import requests
url = 'https://www.courts.com.sg/sitemap/'
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
cats = soup.select('li.level-0.category > a')[:6]
links = [i['href'] for i in cats]
products = []
for link in links:
link += '?product_list_limit=24'
while link:
r = requests.get(link)
soup = BeautifulSoup(r.text, 'html.parser')
link = (soup.select_one('a.action.next') or {}).get('href')
for elem in soup.select(".product-item-info .product-item-link"):
product = elem.get_text(strip=True)
products += [product]
print(product)
我已将每页的产品数量增加到 24 个,但此代码仍然需要大量时间,因为它收集了所有主要类别的产品及其分页链接。但是,我们可以使用threads 使其更快。
from bs4 import BeautifulSoup
import requests
from threading import Thread, Lock
from urllib.parse import urlparse, parse_qs
lock = Lock()
threads = 10
products = []
def get_products(link, products):
soup = BeautifulSoup(requests.get(link).text, 'html.parser')
tags = soup.select(".product-item-info .product-item-link")
with lock:
products += [tag.get_text(strip=True) for tag in tags]
print('page:', link, 'items:', len(tags))
url = 'https://www.courts.com.sg/sitemap/'
soup = BeautifulSoup(requests.get(url).text, 'html.parser')
cats = soup.select('li.level-0.category > a')[:6]
links = [i['href'] for i in cats]
for link in links:
link += '?product_list_limit=24'
soup = BeautifulSoup(requests.get(link).text, 'html.parser')
last_page = soup.select_one('a.page.last')['href']
last_page = int(parse_qs(urlparse(last_page).query)['p'][0])
threads_list = []
for i in range(1, last_page + 1):
page = '{}&p={}'.format(link, i)
thread = Thread(target=get_products, args=(page, products))
thread.start()
threads_list += [thread]
if i % threads == 0 or i == last_page:
for t in threads_list:
t.join()
print(len(products))
print('\n'.join(products))
此代码在大约 5 分钟内从 773 个页面收集了 18,466 个产品。我正在使用 10 个线程,因为我不想给服务器带来太多压力,但您可以使用更多(大多数服务器可以轻松处理 20 个线程)。