我用 python 编写了一个脚本以到达目标页面,其中每个类别在网站中都有其可用的项目名称。我下面的脚本可以从大多数链接中获取产品名称(通过流动类别链接和子类别链接生成)。
该脚本可以解析单击位于每个类别旁边的 +
符号时显示的子类别链接,如下图所示,然后解析目标页面中的所有产品名称。 This is one of such目标页面。
However, few of the links do not have the same depth as other links. For example this link and this one are different from usual links like this one.
如何从所有链接中获取所有产品名称,而不管它们的深度如何?
这是我到目前为止尝试过的:
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
link = "https://www.courts.com.sg/"
res = requests.get(link)
soup = BeautifulSoup(res.text,"lxml")
for item in soup.select(".nav-dropdown li a"):
if "#" in item.get("href"):continue #kick out invalid links
newlink = urljoin(link,item.get("href"))
req = requests.get(newlink)
sauce = BeautifulSoup(req.text,"lxml")
for elem in sauce.select(".product-item-info .product-item-link"):
print(elem.get_text(strip=True))
如何找到 trget 链接:
最佳答案
该网站有六个主要产品类别。属于子类别的产品也可以在主类别中找到(例如 /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
产品。同样,品牌链接中的产品可以在主要类别中找到。例如,/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 个线程)。
关于python - 无法从一些不同深度的链接中解析产品名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52065009/