关于 Python + Selenium 模拟用户搜索轨迹的想法

搜索

很多时候,爬虫是获取原始数据的低成本、高效的途径之一。但随着大数据时代的来临,为了获得更多的数据,很多爬虫无视 robost.txt 协议对内容进行爬取,这也致使一些以数据、内容驱动的企业,都纷纷组建反爬虫团队,也致使爬虫获取数据的成本原来越高。

但这并不是一件坏事,爬与反爬之间的技术升级,推动了行业的发展、丰富了相关组件和类库等等。

为了绕过爬虫的识别,从本质上说,爬虫需要尽可能地模拟正常用户的行为,user agent、cookies、webdriver 特征,甚至是浏览器指纹、用户浏览轨迹等。

像一些硬指标,可以通过 Antibot 去测试,而软指标,例如用户浏览轨迹,就需要花心思研究了。很多人觉得,有时候我们写一个很简单的爬虫,已经可以爬取目标网站的数据,为什么要搞那么复杂?其实你的爬虫能够爬取目标网站的数据,并不意味着对方不知道你是爬虫,只是很多时候,识别爬虫的成本可能会比被爬取的内容的价值高很多,这样就没有必要去进行反爬。

像知乎、微博,往往只要搞定了模拟登录,然后设置好爬取频率,基本能够爬取内容了。但相对于一些对排名敏感的数据,例如百度搜索排名、google 搜索排名等,你的爬虫就需要好好靠谱模拟用户搜索轨迹的问题了。

模拟用户搜索轨迹,实际上也是爬虫的一种应用场景。搜索引擎的排名算法,是一种十分复杂的算法,有兴趣了解的朋友可以看看 Zac 老师写的《SEO 实战密码》。搜索引擎排名,实质上是一种投票机制。过去外链为王的时代,你的网站有一条高质量的外链,就相当于行业内有一个举重轻重的人给你投了一票一样,那么你的网站在搜索结果中,排名就会靠前。而外链也已经被站群玩坏了,百度前几年升级算法时,已经可以精准打击站群、链接农场,现在外链对排名的作用已经是微乎其微了。

而现在内容为王的时代,对应的投票机制注重的是“展现 + 点击”了,而别有用心之人,则利用这个特点来帮助自己的网站达到快速排名的效果,这就是快排。

立场声明:我个人并不建议采用作弊手段来提升网站排名,算法更新时,迟早要被清算的。

现在我们讨论一下一个真实用户的搜索场景:

  1. 用户打开百度/谷歌;
  2. 点击输入框,输入(或黏贴)关键词;
  3. 点击搜索(或按回车);
  4. 等待页面显示结果,然后查看结果;
  5. 如发现有吸引的结果,点击查看;
  6. 浏览详情,觉得结果并不是想要的,关闭页面,返回列表页面;
  7. 重复 5 ~ 6,直到找到相关结果,然后深度浏览;
  8. 浏览完之后,可能会结束搜索,或者继续搜索其他关键词。

我们以百度为例,用简单的代码来一步步探索一下核心思路:

1.打开百度

browser.get('https://www.baidu.com')

2.点击输入框,输入(或黏贴)关键词

这里需要等待搜索框的 html 代码加载完成

wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#kw')))

然后清除搜索框的 placeholder

search_input = browser.find_element(By.CSS_SELECTOR, '#kw')
search_input.clear()

输入关键词

search_input.send('python最新版本')

3.点击搜索(或按回车)

找到搜索按钮,然后模拟移动鼠标到按钮上,再进行点击(这里可以做得更真实一点,封装两种行为:点击按钮和按键盘的 enter 键,然后随机执行一种)。这里必须要使用 python 脚本进行点击,而不能使用 JavaScript,因为使用 JavaScript 点击,浏览器的 isTrusted 属性是 false,对方很容易就可以检测到你是脚本行为。

btn_search = browser.find_element(By.CSS_SELECTOR, '#su')
ActionChains(browser).move_to_element(btn_search).perform()

4.等待页面显示结果,然后查看结果;

5.如发现有吸引的结果,点击查看;

6.浏览详情,觉得结果并不是想要的,关闭页面,返回列表页面;

第 4、5、6 点可以合并在一起操作,那么我们如何模拟这种行为呢。Zac 老师的《SEO 实战密码》曾经说过,百度搜索,90% 的点击流量都在第一页,而这 90% 的流量中的大部分流量,都贡献给第一名的搜索结果。但这只是大部分,并不是全部,而现在百度搜索结果的第一页太多广告,现在很多用户已经不会点击第一条结果了,很多时是滚动浏览器,随机浏览一下。

那么我们先把搜索结果找出来,然后在搜索结果中随机一个索引值出来,把滚动条滚动到大概的位置,把鼠标移动上去,然后点击。

wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#content_left > .result')))
results = self.browser.find_elements(By.CSS_SELECTOR, '#content_left > .result')
# 有多少条结果
len_results = len(results)
# 随机一个点击次数,一般 1 - 3 次
to_click_time = random.randint(1, 3)
# 实际点击次数
clicked_time = 0
# 循环点击
while clicked_time < to_click_time:
    # 这里输入你的逻辑代码

需要注意的是,你的代码里面,务必要加上频率控制,每一个连续操作之间不可太快,因为脚本的速度比人的实际操作速度快得多。否则,很容易就会触发百度的验证码。

百度验证码

按照这个思路,可以自行丰富一下代码,加上自己的业务代码测试一下。

You May Also Like

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注