Проблема разбора названия продукта из некоторых ссылок с разной глубиной - PullRequest
0 голосов
/ 28 августа 2018

Я написал скрипт на python, чтобы добраться до целевой страницы, где у каждой категории есть доступные имена элементов на веб-сайте. Мой скрипт ниже может получить названия продуктов по большинству ссылок (сгенерированных с помощью ссылок на перемещаемые категории, а затем ссылок на подкатегории).

Сценарий может анализировать ссылки на подкатегории, отображаемые при нажатии знака +, расположенного рядом с каждой категорией, которые видны на изображении ниже, а затем анализировать все названия продуктов на целевой странице. Это одна из таких целевых страниц.

Однако немногие ссылки не имеют такой же глубины, как другие ссылки. Например, эта ссылка и эта отличаются от обычных ссылок, таких как эта .

Как я могу получить все названия продуктов по всем ссылкам независимо от их разной глубины?

Это то, что я пробовал до сих пор:

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:

enter image description here

Ответы [ 4 ]

0 голосов
/ 04 сентября 2018

На сайте представлено шесть основных товарных категорий. Продукты, которые относятся к подкатегории, также можно найти в основной категории (например, продукты в /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 rпродукты от /tv-entertainment. Аналогичным образом товары в ссылках на бренды можно найти в основных категориях. Например, продукты /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))

Этот код собирает 18 466 товаров с 773 страниц примерно за 5 минут. Я использую 10 потоков, потому что я не хочу сильно нагружать сервер, но вы можете использовать больше (большинство серверов могут легко обрабатывать 20 потоков).

0 голосов
/ 01 сентября 2018

Поскольку ваша главная проблема - поиск ссылок, вот генератор, который найдет все ссылки на категории и подкатегории, используя карту сайта, указанную 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.

0 голосов
/ 03 сентября 2018

Я увидел сайт для разбора и обнаружил, что все продукты доступны в левой нижней части главной страницы 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

Эта функция вернет список всех продуктов всех категорий, которые ваш код не извлек из него.

0 голосов
/ 30 августа 2018

Я бы порекомендовал начать скрап со страниц карты сайта

Найдено здесь

Если бы они добавили продукты, то, скорее всего, и здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...