无法从具有不同深度的某些链接中解析产品名称

问题描述 投票:11回答:4

我在python中编写了一个脚本来到达目标页面,其中每个类别在网站中都有可用的项目名称。我的下面的脚本可以从大多数链接获取产品名称(通过流动类别链接生成,然后是子类别链接)。

该脚本可以解析在单击位于下图中可见的每个类别旁边的+符号时显示的子类别链接,然后解析目标页面中的所有产品名称。 This is one of such目标页面。

但是,很少链接与其他链接的深度不同。例如,this linkthis onethis 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))

如何查找目标链接:

enter image description here

python python-3.x web-scraping beautifulsoup
4个回答
6
投票

该网站有六个主要产品类别。属于子类别的产品也可以在主要类别中找到(例如,/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。所以,你可以从/televisions获得所有的/tv-entertainment 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个线程)。


2
投票

我建议从页面站点地图开始你的scrape

Found here

如果他们要添加产品,它也可能会出现在这里。


1
投票

由于您的主要问题是找到链接,这里有一个生成器,它将使用他的解决方案中指出的站点地图krflol找到所有类别和子类别链接:

from bs4 import BeautifulSoup
import requests


def category_urls():
    response = requests.get('https://www.courts.com.sg/sitemap')
    html_soup = BeautifulSoup(response.text, features='html.parser')
    categories_sitemap = html_soup.find(attrs={'class': 'xsitemap-categories'})

    for category_a_tag in categories_sitemap.find_all('a'):
        yield category_a_tag.attrs['href']

并找到产品名称,只需刮掉每个产生的category_urls


1
投票

我看到了解析网站,发现所有产品都在主页https://www.courts.com.sg/的左下方可用。点击其中一个后,我们进入特定类别的广告首页。我们必须点击所有产品才能获得它。

以下是整个代码:

import requests
from bs4 import BeautifulSoup

def parser():
    parsing_list = []
    url = 'https://www.courts.com.sg/'
    source_code = requests.get(url)
    plain_text = source_code.text
    soup = BeautifulSoup(plain_text, "html.parser")
    ul = soup.find('footer',{'class':'page-footer'}).find('ul')
    for l in ul.find_all('li'):
        nextlink = url + l.find('a').get('href')
        response = requests.get(nextlink)
        inner_soup = BeautifulSoup(response.text, "html.parser")
        parsing_list.append(url + inner_soup.find('div',{'class':'category-static-links ng-scope'}).find('a').get('href'))
return parsing_list

此函数将返回您的代码未从中获取的所有类别的所有产品的列表。

© www.soinside.com 2019 - 2024. All rights reserved.