用Python发现爱马仕官网特定栏目更新

契机

自从6月份父亲心脏病住院以来,借着在医院一些空余的时间,漫无目的的找来一些网评较好的书:《快乐的Linux命令行》《精通正则表达式》《A Byte of Phton》《MySQL必知必会》《用Python写网络爬虫》《图解HTTP》,除了为了打发时间和想找回点做技术的感觉,另外还有心里一直想着的今年的一个目标:能够获得一笔工资外的收入,无论多少。

偶然一个朋友找到我可不可以帮他想想有什么办法可以替代他一整天盯着爱马仕官网,他为了刷到爱马仕的一些新品,需要一直盯着电脑刷新网站,眼睛都快瞎了。我想了一下,也许我能够通过做点事情来巩固我这段时间看的Python。这段时间看了一些基础后,觉得这个”辅助语言”确实学晚了,它真的很方便、流畅,非常适合通过它来快速验证或学习全栈技术。

实现1

简单了解后,他需要知道网站有上新,上新的标准是什么?网页上面有一个物品的总数,只要这个总数有变化了,那么就代表有上新。那很简单,用requests库就可以搞定了,第一行代码有了resp = requests.get(url),再用xpath解析这个resp的html结构,将total总数获取出来,对比上一次的total总数,即可知道是否有变化。检测到有变化后,通过Twilio免费短信或Email发送通知到订阅者。

问题

手动测试了几次后,发现数目不对,爱马仕官网总是先展示一个静态页面,然后再刷新一次,出现最终的页面。上面的代码只能获取到第一次展示页面的数字,这个数字一般都是不准的。

实现2

使用selenium的webdriver来模拟我们实际情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 浏览器相关设置
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=chrome_options
# 打开小件页面
driver.get(goods_url)
# 新建一个窗口,背包页面
js = 'window.open("{}");'.format(bags_url)
driver.execute_script(js)
# hermes页面加载后会再刷新数字,延时可以获取到正确到数字
time.sleep(10)
1
2
3
4
5
6
7
8
# 几个相关的driver函数
handle = driver.window_handles
driver.switch_to.window(handle)
driver.find_element_by_xpath(x_filter).text # 获取页面的需要的元素
driver.switch_to.window(handle)
driver.refresh()
driver.close()
driver.quit()
问题2
  • 不够轻便
  • 配置复杂,切换服务器的话又得重新下载一系列依赖的软件包。
  • 效率低,要获取的字段很少,但却把整个页面都加载了一遍。
  • 不够稳定,延时时间设置只能靠猜,网络情况不好的情况下还是会获取到静态页面。
  • 可扩展性低

实现3

使用chrome的开发者工具(command+option+i) -> Newwork标签 -> XHR,手动刷新页面,分析一下存在哪些接口交互。很明显可以看到这样一个接口:
https://bck.hermes.com/product?locale=au_en&category=WOMENBAGSSMALLLEATHER&sort=relevance
接口返回了totol总数,还返回了porducts列表,一页强制只返回36个产品数据,所以想获取到该栏目所有的产品还得再确认一下如何翻页,经过简单的推断和尝试拼装参数可以得到一个接口:
https://bck.hermes.com/product?locale=au_en&category=WOMENBAGSSMALLLEATHER&sort=relevance&offset={0}
有了products这个属性,就可以分析对比上一次增加或较少了什么产品了,整体大概流程如图:

问题
  1. 每次大概跑个48小时候就会假死
  2. 跑得太快ip被封了
  3. 打印导致崩溃
解决
  1. socket.setdefaulttimeout(60) requests设置超时时间
  2. 云主机被封ip了没救了,用自己的vps架了squid代理,调低频率。夜间不跑。
  3. sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())

总结:

有趣的探索过程,从配置服务器环境、代码管理、Python学习、反爬虫、sqlite复习、用pandas库分析一天到底上上下下些了什么,甚至到小红书去拉客户,一套打下来,给了自己很多启发。

0%