你做的工作比你必须做的要多——我是说 Selenium。访问该页面时,我使用 Google Chrome 的开发工具记录了我的网络流量,我看到我的浏览器向 REST API 发出了 HTTP GET 请求,其响应是 JSON 并包含您可能想要的所有葡萄酒/价格信息.因此,您无需进行任何刮擦。只需使用所需的查询字符串参数和正确的标头来模仿该 GET 请求。似乎 REST API 只关心 user-agent 标头,这是微不足道的。
- 首先访问URL
在谷歌浏览器中。
- 按
F12 键打开 Google Chrome 开发工具菜单。
点击Network 标签。
- 单击圆形记录按钮。它应该变红,它会
开始在下面的日志中记录所有网络流量。点击
旁边的过滤按钮,然后点击
XHR。这只会
在日志中显示 XHR (XmlHttpRequest) 请求。我们感兴趣
特别是这些请求,因为它是通过 XHR 请求
通常制作 API。它现在应该是这样的:
- 在 Chrome 开发工具菜单仍然打开的情况下,右键单击(不是
左键单击)页面刷新按钮以显示下拉菜单。
然后,点击
Empty Cache and Hard Reload。
这将清空您浏览器对该页面的缓存,并强制您
浏览器刷新页面。当页面被刷新时,您
应该开始看到一些条目出现在流量日志中。
现在日志中应该有一些 XHR 请求条目。我们不知道其中哪一个是我们真正感兴趣的,所以我们只是查看所有这些,直到找到一个看起来可能是正确的(或者,如果它包含我们的信息)重新寻找,如个别葡萄酒的信息等)。我碰巧知道我们对以explore?... 开头的那个感兴趣,所以让我们点击它。
- 单击条目后,将在右侧打开一个面板
日志。点击
Headers 标签。
此选项卡包含有关如何提出此请求的所有信息。在General 区域下,您可以看到Request URL,这是我们向其发出请求的 REST API 端点的 URL。这个 URL 可能很长,因为它通常还包含查询字符串参数(那些是在 explore? 之后的键值对,例如 country_code=DE 或 currency_code=EUR。它们由 & 分隔) .查询字符串参数很重要,因为它们包含有关我们要应用于查询的某些过滤器的信息。在我的代码示例中,我已将它们从 REST API 端点 URL 中删除,而是将它们移动到 params 字典中。此步骤不是必需的 - 您也可以将它们留在 URL 中,但我发现这种方式更易于阅读和修改。查询字符串参数也很重要,因为有时某些 API 会期望某些参数出现在请求中,或者他们会期望它们具有某些值 - 换句话说,某些 API 对其查询字符串参数非常挑剔,如果您以 API 未预料到的方式删除或篡改它们,API 会说您的请求表述不正确。
在General 区域,您还可以看到Request Method,在我们的例子中是GET。这告诉我们,我们的浏览器发出了 HTTP GET 请求。并非所有 API 端点的工作方式都相同,有些需要 HTTP POST 等。
Status Code 告诉我们服务器发回的状态码。 200 表示一切正常。您可以了解更多关于HTTP status codes here的信息。
让我们看看Response Headers 区域。该区域包含服务器在发出请求后发回的所有响应标头。这些对于浏览器来说非常有用,例如设置 cookie 或了解如何解释服务器发回的数据。
Request Headers 区域包含您的浏览器在发出请求时发送到服务器的所有标头。通常,复制所有这些键值对并将它们转换为 Python 字典 headers 是个好主意,因为这样可以确保 Python 脚本会发出与浏览器发出的完全相同的请求。但是,通常,我喜欢尽可能地减少它。我知道许多 API 非常关心 user-agent 字段,所以通常我会保留那个,但有时他们也关心 referer。当您使用不同的 API 时,您必须通过反复试验找出 API 关心的请求标头。这个 API 恰好只关心user-agent。
最后一个区域Query String Parameters 只是在一个人性化的键值对列表中显示来自Request URL 的查询字符串参数的一种可爱方式。有时从此处而不是从 URL 复制它们会很有帮助。
- 现在,点击
Preview 标签旁边的Headers 标签。
Preview 选项卡包含一个漂亮打印的预览,显示了作为浏览器请求的结果发回的实际数据。在我们的例子中,它包含服务器发回的 JSON 数据。您可以单击灰色的小三角形来展开或折叠 JSON 结构的某些部分,以显示不同的数据。
看这个,我可以看出 JSON 响应是一个大字典,它有一个键 explore_vintage,它的值是另一个字典,它有一个键 records,它的值是一个字典列表,其中每个此列表中的字典表示一个葡萄酒对象。展开第一个记录(第 0 个)会显示有关列表中第一个葡萄酒的所有信息。您可以随意探索这些结构,看看您可以获得哪些类型的信息。
def main():
import requests
url = "https://www.vivino.com/api/explore/explore"
params = {
"country_code": "DE",
"currency_code": "EUR",
"grape_filter": "varietal",
"min_rating": "3.5",
"order_by": "ratings_average",
"order": "desc",
"page": "1",
"price_range_max": "30",
"price_range_min": "7",
"wine_type_ids[]": "1"
}
headers = {
"user-agent": "Mozilla/5.0"
}
response = requests.get(url, params=params, headers=headers)
response.raise_for_status()
records = response.json()["explore_vintage"]["records"]
for record in records:
name = record["vintage"]["name"]
price = record["price"]["amount"]
currency = record["price"]["currency"]["code"]
print(f"\"{name}\" - Price: {price} {currency}")
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
输出:
"Varvaglione Cosimo Varvaglione Collezione Privata Primitivo di Manduria 2015" - Price: 21.9 EUR
"Masseria Borgo dei Trulli Mirea Primitivo di Manduria 2019" - Price: 19.9 EUR
"Vigneti del Salento Vigne Vecchie Primitivo di Manduria 2016" - Price: 22.95 EUR
"Vigneti del Salento Vigne Vecchie Leggenda Primitivo di Manduria 2016" - Price: 17.87 EUR
"Varvaglione Papale Linea Oro Primitivo di Manduria 2016" - Price: 18.85 EUR
"Caballo Loco Grand Cru Apalta 2014" - Price: 27.9 EUR
"Luccarelli Il Bacca Old Vine Primitivo di Manduria 2016" - Price: 20.9 EUR
"Mottura Stilio Primitivo di Manduria 2018" - Price: 12.89 EUR
"Caballo Loco Grand Cru Maipo 2015" - Price: 24.81 EUR
"Lorusso Michele Solone Primitivo 2017" - Price: 21.39 EUR
"Château Purcari Negru de Purcari 2017" - Price: 29.8 EUR
"San Marzano 60 Sessantanni Limited Edition Old Vines Primitivo di Manduria 2016" - Price: 22.85 EUR
"San Marzano 60 Sessantanni Old Vines Primitivo di Manduria 2016" - Price: 20.9 EUR
"San Marzano 60 Sessantanni Old Vines Primitivo di Manduria 2017" - Price: 17.775 EUR
"Lenotti Amarone della Valpolicella Classico 2015" - Price: 27.95 EUR
"Zeni Cruino Rosso Veronese 2015" - Price: 22.9 EUR
"Masseria Pietrosa Palmenti Primitivo di Manduria Vigne Vecchie 2016" - Price: 25 EUR
"Ravazzi Prezioso 2016" - Price: 29.95 EUR
"Nino Negri Sfursat Carlo Negri 2017" - Price: 23.89 EUR
"Quinta do Paral Reserva Tinto 2017" - Price: 29.24 EUR
"Wildekrans Barrel Select Reserve Pinotage 2016" - Price: 29.9 EUR
"Caballo Loco Grand Cru Limarí 2016" - Price: 27.9 EUR
"San Marzano F Negroamaro 2018" - Price: 16.9 EUR
"Atlan & Artisan 8 Vents Mallorca 2018" - Price: 19 EUR
"Schneider Rooi Olifant Red 2017" - Price: 19.5 EUR
>>>
它似乎每页抓取 25 条记录/葡萄酒,但是更改 params 查询字符串参数字典中的 page 键值对将产生您想要的任何页面的记录。我目前位于德国,这就是为什么我的 country_code 和 currency_code 是 "DE" 和 "EUR",但您应该能够根据自己的需要进行更改。
编辑 - 这里还有一些您可能感兴趣的键值对,不过我建议您熟悉浏览器的开发工具的工作原理,以便您自己在 JSON 中发现这些字段:
record["vintage"]["year"]
record["vintage"]["wine"]["region"]["name"]
record["vintage"]["wine"]["region"]["country"]["name"]
record["vintage"]["wine"]["taste"]["structure"]["acidity"]
record["vintage"]["wine"]["taste"]["structure"]["intensity"]
record["vintage"]["wine"]["taste"]["structure"]["sweetness"]
record["vintage"]["wine"]["taste"]["structure"]["tannin"]
record["vintage"]["wine"]["style"]["grapes"][0]["name"] # 0th grape information
record["vintage"]["wine"]["winery"]["name"]
不幸的是,JSON 不包含酒精含量。此信息被硬编码在给定葡萄酒摘要页面的 HTML 中。您必须向每个葡萄酒摘要页面发出请求,并从页面中提取酒精含量值,可能使用正则表达式。