Python 从某些深度不同的链接中解析产品名称时遇到问题
我已经用python编写了一个脚本,以到达目标页面,其中每个类别在网站中都有可用的项目名称。我下面的脚本可以从大多数链接(通过巡回类别链接和子类别链接生成)中获取产品名称 该脚本可以解析在单击下图中可见的每个类别旁边的Python 从某些深度不同的链接中解析产品名称时遇到问题,python,python-3.x,web-scraping,beautifulsoup,Python,Python 3.x,Web Scraping,Beautifulsoup,我已经用python编写了一个脚本,以到达目标页面,其中每个类别在网站中都有可用的项目名称。我下面的脚本可以从大多数链接(通过巡回类别链接和子类别链接生成)中获取产品名称 该脚本可以解析在单击下图中可见的每个类别旁边的+符号时显示的子类别链接,然后解析目标页面中的所有产品名称。目标页面 但是,很少有链接与其他链接的深度不同。例如,和通常的链接不同,如 如何从所有链接中获取所有产品名称,而不管其深度如何? 这就是我迄今为止所尝试的: import requests from urllib.pars
+
符号时显示的子类别链接,然后解析目标页面中的所有产品名称。目标页面
但是,很少有链接与其他链接的深度不同。例如,和通常的链接不同,如
如何从所有链接中获取所有产品名称,而不管其深度如何?
这就是我迄今为止所尝试的:
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链接:
我建议您从网页网站地图开始抓取
如果他们要添加产品,很可能也会出现在这里。因为您的主要问题是查找链接,这里有一个生成器,它将使用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']
要找到产品名称,只需刮取每个产生的
类别\u URL
我看到了要解析的网站,发现所有产品都位于主页的左下角。单击其中一个后,我们进入特定类别的广告首页。我们必须进入的地方单击所有产品以获取它
以下是整个代码:
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
此函数将返回代码未从中删除的所有类别的所有产品的列表 该网站有六个主要产品类别。属于子类别的产品也可以在主类别中找到(例如
/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
。但是,如果您单击该页面上的查看所有产品
链接,您将被重定向到/tv entertainment/vision/tv
。因此,您可以从/tv entertainment
获取所有/tv
产品。同样,与品牌相关的产品也可以在主要类别中找到。例如,/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个,但这段代码仍然需要很多时间,因为它收集所有主要类别的产品及其分页链接。然而,我们可以通过使用
此代码在大约5分钟内从773页中收集18466个产品。我使用10个线程是因为我不想给服务器太大的压力,但是你可以使用更多的线程(大多数服务器可以轻松处理20个线程) 为什么URL的深度很重要?这有什么变化?如果你读了@Cole的帖子,那么深度为什么会更重要呢。然而,当现有的逻辑被应用到scraper中时,这不允许我从这些链接(包含不同的深度)获取产品名称。考虑到这些要求,链接的格式不是你想要实现的目标。除非我遗漏了什么?希望解析所有的产品名称,就这样。这仍然会带来相同的深度问题。查看此链接
https://www.courts.com.sg/klipsch
,https://www.courts.com.sg/simmons
与这两个不同的深度https://www.courts.com.sg/home-appliances/small-appliances
,https://www.courts.com.sg/smart-tech/smart-gadgets
等等。@Topto您正在解析URL本身的数据吗?看来这个线程现在可以解决了。发现你在圈中总是很高兴@t.m.adam。在脚本中,我应该在何处以及如何使用print
语句?到时候我会接受的。谢谢。我很高兴看到你还在身边,伙计!我想您可以打印循环中的每个产品(我已经更新了代码)。顺便问一下,你觉得我的解决方案怎么样?我搜索了一下这个网站,我认为主要的分类包括所有的产品。请让我知道,如果你发现一个产品,是不是在一个主要类别,所以我可以看看。另外,我尝试使用多线程,因为脚本太慢了。如果可以的话,我会更新代码。
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))