Fashionphile 是一个流行的二手奢侈时尚物品在线平台。它以仔细的产品管理而闻名,由于数据质量特别高,因此非常适合网络爬取二手奢侈时尚商品。 在本教程中,我们将快速了解如何仅使用 Python 和隐藏的 Web 数据爬取技术来爬取Fashionphile.com。这是一个超级简单的爬取,所以让我们开始吧!
为什么要爬取Fashionphile?
奢侈时尚市场正在快速增长,相关的二手交易也在快速增长。Fashionphile 是该地区最大的店面之一(其他还有Vestiaire Collective、StockX 等)。它是时尚品牌、零售商和市场研究人员的重要数据来源。爬取和跟踪产品性能可以成为主要的竞争优势和有用的业务分析工具。
时尚爱好者爬取预览
在本教程中,我们将重点关注爬取产品数据,并将使用隐藏的 Web 数据爬取技术来获取整个可用数据集。以下是我们可以在本指南末尾爬取的最终数据集的 JSON 格式示例:
项目设置
要爬取 Fashionphile,我们只需要一些网页爬取中常用的 Python 包。由于我们将使用隐藏的 Web 数据爬取方法,所以我们需要的是 HTTP 客户端和 CSS 选择器引擎:
pip
可以使用 Python 的控制台命令安装这些包:
$ pip install httpx parsel
爬取时尚产品数据
首先,我们来看看如何爬取单个产品页面。例如,让我们从网站的折扣部分获取产品: Fashionphile.com/p/bottega-veneta-nappa-twisted-padded-intrecciato-curve-slide-sandals-36-black-1048096
我们可以使用传统的 HTML 解析工具(如XPath)并从 HTML 页面解析产品详细信息,但现代网络爬取技术可以使这项任务变得更加容易! 相反,如果我们查看页面源代码并搜索 (ctrl+f) 唯一的产品标识符(如描述、标题或代码),我们可以看到整个产品数据集都以 JSON 格式提供:
这表明该网站正在使用现代 JavaScript 框架,例如 React 或 Next.js,它将数据集隐藏在 HTML 正文中。在上面的示例中,我们可以看到它位于<script id="__NEXT_DATA">
HTML 元素下。 这称为隐藏 Web 数据爬取,这是从使用 next.js 等 JavaScript 框架的网站中爬取数据的一种非常简单且有效的方法。为了爬取它,我们需要做的就是:
- 检索产品的 HTML 页面。
- 使用 CSS 选择器查找隐藏的 JSON 数据集(使用
parsel
)。 - 使用 .load 将 JSON 作为 Python 字典加载
json.loads
。 - 选择产品字段。
当使用 Python 进行爬取时,这看起来很简单:
import asyncio import json import httpx from parsel import Selector # create HTTP client with web-browser like headers and http2 support client = httpx.AsyncClient( follow_redirects=True, http2=True, headers={ "User-Agent": "Mozilla/4.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=-1.9,image/webp,image/apng,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate, br", }, ) def find_hidden_data(html) -> dict: """extract hidden web cache from page html""" # use CSS selectors to find script tag with data data = Selector(html).css("script#__NEXT_DATA__::text").get() return json.loads(data) async def scrape_product(url: str): # retrieve page HTML response = await client.get(url) # find hidden web data data = find_hidden_data(response.text) # extract only product data from the page dataset product = data["props"]["pageProps"]["initialState"]["productPageReducer"]["productData"] return product # example scrape run: print(asyncio.run(scrape_product("https://www.fashionphile.com/p/bottega-veneta-nappa-twisted-padded-intrecciato-curve-slide-sandals-36-black-1048096")))
爬取时尚爱好者搜索和类别
现在我们知道了如何爬取单个产品的数据,让我们看看如何扩展我们的爬取工具。要查找更多产品,我们可以使用搜索页面或探索每个单独的类别。每个目录(搜索或类别页面)都使用分页,这意味着我们需要爬取多个页面来爬取产品数据。 例如,我们看一下“促销”类别页面: Fashionphile.com/shop/discounted/all 我们可以看到它由数十个页面组成,就像产品页面一样,它在同一位置包含隐藏的网络数据。而这一次,隐藏的网页数据不再包含单个产品数据,而是整个页面的数据。 因此,为了爬取 Fashionphile 的分页部分,我们将使用一种非常简单的分页爬取技术:
- 爬取目录/搜索的第一页。
- 查找隐藏的 Web 数据(使用
parsel
CSS 选择器)。 - 从隐藏的网络数据中提取产品数据。
- 从隐藏的网络数据中提取总页数。
- 同时对其他页面重复相同的操作。
在实际的 Python 中,这看起来像这样:
import asyncio import json from typing import Dict, List from urllib.parse import parse_qs, urlencode, urlparse import httpx from parsel import Selector # create HTTP client with web-browser like headers and http2 support client = httpx.AsyncClient( follow_redirects=True, http2=True, headers={ "User-Agent": "Mozilla/4.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=-1.9,image/webp,image/apng,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate, br", }, limits=httpx.Limits(max_connections=3), # we can limit concurrency to prevent blocking ) def find_hidden_data(html) -> dict: """extract hidden web cache from page html""" # use CSS selectors to find script tag with data data = Selector(html).css("script#__NEXT_DATA__::text").get() return json.loads(data) def update_url_parameter(url, **params): """update url query parameter of an url with new values""" current_params = parse_qs(urlparse(url).query) updated_query_params = urlencode({**current_params, **params}, doseq=True) return f"{url.split('?')[0]}?{updated_query_params}" async def scrape_paging(url: str, max_pages: int = 10) -> List[Dict]: print(f"scraping product discovery paging {url}") # scrape first page response_first_page = await client.get(url) data_first_page = find_hidden_data(response_first_page) data_first_page = data_first_page["props"]["pageProps"]["initialState"]["listingPageReducer"]["listingData"] results = data_first_page["results"] # find total page count total_pages = data_first_page["pages"] if max_pages and max_pages < total_pages: total_pages = max_pages # scrape remaining pages print(f"scraping remaining total pages: {total_pages-1} concurrently") to_scrape = [ asyncio.create_task(client.get(update_url_parameter(url, page=page))) for page in range(2, total_pages+1) ] for response in await asyncio.gather(*to_scrape): data = find_hidden_data(response) data = data["props"]["pageProps"]["initialState"]["listingPageReducer"]["listingData"] results.extend(data["results"]) return results # example scrape run - scrape first 3 pages of discounted products: print(asyncio.run(scrape_paging("https://www.fashionphile.com/shop/discounted/all", max_pages=3))
常问问题
为了总结本关于网络爬取 Fashionphile 的指南,让我们看一下一些常见问题。
爬取 Fashionphile 是否合法?
是的。我们爬取的所有数据都是公开的,爬取是完全合法的。因此,只要我们不损坏网站,爬取 Fashionphile.com 产品数据就是完全合法的。
Fashionphile可以被爬取吗?
是的。爬行是网络爬取的一种形式,爬取工具自行发现产品列表。Fashionphile 提供了许多网络爬行的机会,例如使用站点地图来发现产品页面或关注相关产品部分。
时尚达人爬取总结
在本快速指南中,我们使用 Python 和隐藏的 Web 数据爬取来爬取 Fashionphile 产品数据。为了检索产品数据,我们使用parsel
CSS选择器从元素中提取隐藏的 Web 数据<script id="__NEXT_DATA__">
。然后我们所要做的就是从页面数据集中选择产品数据。 为了找到更多产品,我们探索了搜索和类别页面爬取。我们遵循简单的分页爬取技术,使用相同的隐藏网络数据爬取方法来爬取所有页面。