Python | 爬虫实战——亚马逊搜索页监控(附详细源码)

2024-09-05 00:36

本文主要是介绍Python | 爬虫实战——亚马逊搜索页监控(附详细源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

做亚马逊店铺,如果你的品卖爆了,免不得遇到被人跟品、广告关键词竞争甚至是恶意投诉等事情。

如果靠人去检查产品是否正常,存在不及时的问题。

所以,基本都会想要有一个自动检测的工具。

一般是自动根据关键词,设置邮编,查看对应市场下的搜索结果页是否,然后进一步判断搜索结构页的内容是否符合预期,比如该广告词搜索结果是否存在自家产品?自己产品是否占据视频广告位?自己产品的自然排位在第几位?广告排位在第几位?有哪些竞品?……

只要能拿到这个搜索结果页,你就能自动提取和检测多个信息。

所以关键的问题是,自动获取这个搜索结果页。

方案

自动抓取亚马逊搜索结果页逻辑,本质上也比较简单,就是一个 HTTP 请求而已。

关于爬虫技术,可以参考:《认识爬虫技术》

但想要达到预期效果,面对亚马逊这个平台,有 2 个需要克服的问题:

  1. 需要设置目标市场的邮编,实现和用户实际搜索一样的市场范围。

  2. 需要克服亚马逊的反爬虫机制。

邮编设置

亚马逊的邮编信息设置,如下设置为 17888:

我没有登录,可以随意更改。

说明这个邮编信息,肯定是存在前端缓存中,那一般就在 cookie 中。

我们可以 F12 查看 cookie,但是找不到邮编对应的 cookie 信息:

但可以看到有一个 session-token 信息,大概率邮编是加密保存在其中。

这些 cookie 信息过期时间都是 1 年,所以我们可以直接把 cookie 信息放入我们的请求脚本。

查看搜索的网络请求,如下,可以看到有个 Cookie 的请求头,把上面的 cookie 信息全部包含在其中。

我们可以直接复制这个 Cookie 请求头,加入 HTTP 请求头就能实现 17888 设置邮编一样的效果。

反爬虫设置

测试下来,亚马逊的反爬虫,和大多数爬虫一样:

  1. 检查 UA 和其他请求头

  2. 检查 Cookie 信息

  3. 检查请求频率

直接在脚本 HTTP 请求头中,把上面 F12 查看到的请求头完整加入理论上就可以了,如下:

import aiohttp
import asyncio
import os
import timedef save_html(content):# 确保目录存在directory = "page"if not os.path.exists(directory):os.makedirs(directory)# 生成文件名filename = time.strftime("%Y%m%d%H%M%S") + ".html"filepath = os.path.join(directory, filename)# 保存文件with open(filepath, 'w', encoding='utf-8') as file:file.write(content)print("页面已保存至:", filepath)async def monitor_amazon():headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding": "gzip, deflate, br, zstd","Connection": "keep-alive","Host": "www.amazon.com","Pragma": "no-cache","Cache-Control": "no-cache","device-memory": "8","sec-ch-device-memory": "8","dpr": "1","sec-ch-dpr": "1","viewport-width": "1287","sec-ch-viewport-width": "1287","rtt": "250","downlink": "10","ect": "4g","sec-ch-ua": '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"',"sec-ch-ua-mobile": "?0","sec-ch-ua-platform": '"Windows"',"sec-ch-ua-platform-version": '"15.0.0"',"Upgrade-Insecure-Requests": "1","Sec-Fetch-Site": "none","Sec-Fetch-Mode": "navigate","Sec-Fetch-User": "?1","Sec-Fetch-Dest": "document","Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,fr;q=0.6","Cookie": "csm-sid=561-4363494-2586590; x-amz-captcha-1=1725426766590873; x-amz-captcha-2=coU0U1XjNmbWBo6t12F7Lw==; session-id=145-8557831-0273963; session-id-time=2082787201l; i18n-prefs=USD; ubid-main=135-5704831-0797008; skin=noskin; JSESSIONID=12AD7B880D398809E2385F69B353506A; session-token=JswlXQfSLBxq71q7wIMJNajjv7zTDlFSxhu+hA1idTc8X3yk1TP/yeQ8rBlKWLJXeMAX0cKAUM7NXYe/LmmGgsv9F44l0Q8EI43IanRD9e6XgYsSra04Q0RiAjvrZfAFRf6Gn222CjZ9PAAzzQ7YPq7qx5jEeaOKgtj3t0VkGVlKmTX3wWbnoIv1wJRAv3R9b3BgnIDgYX64V9hxyZQaobLX8LeI70c9uTD3bw8nOz5VMjHkdF4F8x1dzXZZp6QhmVe/ESi1qlfF2PQnt0JgHp2J+3xsDmq7rL8ogs0/haZAkS16oTC5w3ghPAuvqskUKvZRnmp6m8Xag6GSK37kmDkVr7pwyWB/; csm-hit=tb:YBQ9G3J9FVM18YJJW7QJ+s-YBQ9G3J9FVM18YJJW7QJ|1725430067985&t:1725430067985&adb:adblk_no",}# 监控的产品,搜索词keyword = "cat litter"asin = "B0CR919N3T"search_url = f"https://www.amazon.com/s?k={keyword.replace(' ', '+')}"async with aiohttp.ClientSession() as session:response = await session.get(search_url, headers=headers)html = await response.text()await session.close()save_html(html)if "dogs of amazon" in html.lower():print("搜索被标识为异常访问")elif asin.lower() in html.lower():print("在 Amazon 搜索结果页找到了关键词")else:print("在 Amazon 搜索结果页未找到 ASIN 关键词,发送警告")# 在 Windows 中使用 SelectorEventLoop
if __name__ == '__main__':if os.name == 'nt':loop = asyncio.SelectorEventLoop()asyncio.set_event_loop(loop)else:loop = asyncio.get_event_loop()loop.run_until_complete(monitor_amazon())loop.close()

代码很简单,抓取到页面后,但是,只有偶尔能成功获取到一次正常的页面,其他页面全部变 "狗",如下:

这个页面返回,明显是触发了亚马逊的返爬虫机制。

后续我尝试使用了海外的代理 IP,替换了多个和网页请求一致的请求头,但仍然一样。

相同的代码逻辑,我又改成了 Golang 脚本:

package mainimport ("fmt""io/ioutil""net/http""os""time"
)func saveHTML(content []byte) {directory := "page"// 确保目录存在if _, err := os.Stat(directory); os.IsNotExist(err) {os.Mkdir(directory, os.ModePerm)}// 生成文件名filename := time.Now().Format("20060102150405") + ".html"filepath := directory + "/" + filename// 保存文件err := ioutil.WriteFile(filepath, content, 0644)if err != nil {fmt.Println("保存文件失败:", err)} else {fmt.Println("页面已保存至:", filepath)}
}func monitorAmazon() {client := &http.Client{}// 创建请求req, err := http.NewRequest("GET", "https://www.amazon.com/s?k=cat+litter", nil)if err != nil {fmt.Println("创建请求失败:", err)return}// 设置请求头req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")req.Header.Set("Connection", "keep-alive")req.Header.Set("Host", "www.amazon.com")req.Header.Set("Pragma", "no-cache")req.Header.Set("Cache-Control", "no-cache")req.Header.Set("device-memory", "8")req.Header.Set("sec-ch-device-memory", "8")req.Header.Set("dpr", "1")req.Header.Set("sec-ch-dpr", "1")req.Header.Set("viewport-width", "1287")req.Header.Set("sec-ch-viewport-width", "1287")req.Header.Set("rtt", "250")req.Header.Set("downlink", "10")req.Header.Set("ect", "4g")req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"`)req.Header.Set("sec-ch-ua-mobile", "?0")req.Header.Set("sec-ch-ua-platform", `"Windows"`)req.Header.Set("sec-ch-ua-platform-version", `"15.0.0"`)req.Header.Set("Upgrade-Insecure-Requests", "1")req.Header.Set("Sec-Fetch-Site", "none")req.Header.Set("Sec-Fetch-Mode", "navigate")req.Header.Set("Sec-Fetch-User", "?1")req.Header.Set("Sec-Fetch-Dest", "document")req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,fr;q=0.6")req.Header.Set("Cookie", "xxx cookie")  // 直接复制浏览器网络请求头中的 Cookie 值// 执行请求resp, err := client.Do(req)if err != nil {fmt.Println("执行请求失败:", err)return}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println("读取响应失败:", err)return}fmt.Println("页面长度:", len(body))saveHTML(body)// 检测页面信息if asin := "B0CR919N3T"; string(body) != "" && string(body) != asin {fmt.Println("在 Amazon 搜索结果页未找到关键词,发送警告")} else {fmt.Println("在 Amazon 搜索结果页找到了关键词")}
}func main() {monitorAmazon()
}

很神奇的是,你会发现 Golang 这个脚本就可以获取到正确的页面。

这也太奇怪了,都是相同的 IP,说明和 IP 没有关系。

所以就打算用抓包工具抓两个脚本的请求明细,看看是否存在区别。

先在 Python 脚本中,增加了代理,抓包如下:

很神奇的是,直接执行脚本,返回内容只有长度为 2671 的变狗页面。

但通过抓包工具代理执行后,竟然能返回正常的页面。

差别在哪里呢?

仔细查看了抓包请求头信息和自己设置的请求头信息,完全一样,没差别。

那唯一的差别就是抓包工具代理了 HTTP 请求,抓包工具用了自己的 HTTP 请求包。

也就是说,唯一的差别就是 HTTP 客户端有差别。

这一下有了思路。

把 python 脚本使用地 requests 包替换成其他 http 工具包。

试了 urllib3、aiohttp。

我发现用 urllib3 和 request 包请求是一样地问题,一查才知道,requests 包底层处理 HTTP 请求时,就是用的urllib3,所以这两个 http 客户端工具包,本质上是同源的。

换成 aiohttp,瞬间,一切正常,不用加 IP 代理,保持源代码,只是换一个 http 工具包而已。

完整代码如下:

import aiohttp
import asyncio
import os
import timedef save_html(content):# 确保目录存在directory = "page"if not os.path.exists(directory):os.makedirs(directory)# 生成文件名filename = time.strftime("%Y%m%d%H%M%S") + ".html"filepath = os.path.join(directory, filename)# 保存文件with open(filepath, 'w', encoding='utf-8') as file:file.write(content)print("页面已保存至:", filepath)async def monitor_amazon():headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding": "gzip, deflate, br, zstd","Connection": "keep-alive","Host": "www.amazon.com","Pragma": "no-cache","Cache-Control": "no-cache","device-memory": "8","sec-ch-device-memory": "8","dpr": "1","sec-ch-dpr": "1","viewport-width": "1287","sec-ch-viewport-width": "1287","rtt": "250","downlink": "10","ect": "4g","sec-ch-ua": '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"',"sec-ch-ua-mobile": "?0","sec-ch-ua-platform": '"Windows"',"sec-ch-ua-platform-version": '"15.0.0"',"Upgrade-Insecure-Requests": "1","Sec-Fetch-Site": "none","Sec-Fetch-Mode": "navigate","Sec-Fetch-User": "?1","Sec-Fetch-Dest": "document","Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,fr;q=0.6","Cookie": "xxx",   # 直接从你设置邮编后的亚马逊网页 F12 查看获取}# 监控的产品,搜索词keyword = "cat litter"asin = "B0CR919N3T"search_url = f"https://www.amazon.com/s?k={keyword.replace(' ', '+')}"async with aiohttp.ClientSession() as session:response = await session.get(search_url, headers=headers)html = await response.text()await session.close()save_html(html)if "dogs of amazon" in html.lower():print("搜索被标识为异常访问")elif asin.lower() in html.lower():print("在 Amazon 搜索结果页找到了关键词")else:print("在 Amazon 搜索结果页未找到 ASIN 关键词,发送警告")# 在 Windows 中使用 SelectorEventLoop
if __name__ == '__main__':if os.name == 'nt':loop = asyncio.SelectorEventLoop()asyncio.set_event_loop(loop)else:loop = asyncio.get_event_loop()loop.run_until_complete(monitor_amazon())loop.close()

能正常获取页面后,剩下的问题就要根据场景来处理。

如果你获取的频率很高,每分钟要获取好几次,那就必须引入动态 IP 代理。

如果频率很低,如果时保护自己产品不被恶意投诉下架,如代码示例判断产品是否还正常存在,那 10 分钟查一次就够了,这种频率,单个 IP 也没问题。

希望对你有帮助。

顺手点个收藏+赞呗~

 

这篇关于Python | 爬虫实战——亚马逊搜索页监控(附详细源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1137480

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount