破解反爬虫的方法
“反爬虫”主要是针对“恶意的爬虫程序”所设计的防堵技术,许多网站为了保护数据或减少网页负担,多少都会加入一些“反爬虫”机制,本篇教学将会介绍一些破解反爬虫的方法,可以针对一些简单的反爬虫机制,进行对应的处理。
快速导览:
执行 selenium 会启动 chromedriver,所以所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) 。
常见的反爬虫方式
“反爬虫”主要是针对“恶意的爬虫程序”所设计的防堵技术,许多网站为了保护数据、减少网页负担、或避免网页上的公开信息被网页爬虫给抓取,多少都会押入一些“反爬虫”机制,常见的反爬虫机制有下列几种:
判断浏览器 headers 信息
利用 headers 判断来源是否合法,headers 通常会由浏览器自动产生,直接透过程序所发出的请求默认没有 headers,破解难度:低。
使用动态页面
将网页内容全部由动态产生,大幅增加爬虫处理网页结构的复杂度,破解难度:中低。
加入用户行为判断
在网页的某些元素,加入用户行为的判断,例如鼠标移动顺序、鼠标是否接触...等,增加爬虫处理的难度,破解难度:中。
模拟真实用户登录授权
在用户登录时,会将用户的授权 ( token ) 加入浏览器的 Cookie 当中,借由判断 Cookie 确认用户是否合法,破解难度:中。
加入验证码机制
相当常见的验证机制,可相当程度的防堵恶意的干扰与攻击,对于非人类操作与大量频繁操作都有不错的防范机制 ( 例如防堵高铁抢票、演唱会抢票...等 ),破解难度:高。
封锁代理服务器与第三方 IP
针对恶意攻击的 IP 进行封锁,破解难度:高
加入浏览器 headers 信息
针对“判断浏览器 headers 信息”的网页,只要能透过爬虫程序,送出模拟浏览器的 headers 信息,就能进行破解。
模拟 headers 常用的内容:
Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36或
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
使用 Requests 函数库:
import requests
url = '要爬的網址'
# 假的 headers 資訊
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'}
# 加入 headers 資訊
web = requests.get(url, headers=headers)
web.encoding = 'utf8'
print(web.text)
使用 Selenium 函数库:
from selenium import webdriver
# 假的 headers 資訊
user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15"
opt = webdriver.ChromeOptions()
# 加入 headers 資訊
opt.add_argument('--user-agent=%s' % user_agent)
driver = webdriver.Chrome('./chromedriver', options=opt)
driver.get('要爬的網址')
清空 window.navigator
有些反爬虫的网页,会检测浏览器的 window.navigator 是否包含 webdriver 属性,在正常使用浏览器的情况下,webdriver 属性是 undefined,一旦使用了 selenium 函数库,这个属性就被初始化为 true,只要借由 Javascript 判断这个属性,就能简单的进行反爬虫。
下方的程序使用 selenium webdriver 的 execute_cdp_cmd 的方法,将 webdriver 设定为 undefined,就能避开这个检查机制。
from selenium import webdriver
driver = webdriver.Chrome('./chromedriver')
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
解析动态页面
针对“使用动态页面”的网页,只要确认动态页面的架构,就能进行破解,如果打开的网页是动态页面,“检视网页源代码”时看到的结构往往会很简单,通常都只会是一些简单的 HTML、CSS 和压缩过的 js 文件。
这时可以使用 Chrome 打开网页,在网页任意位置按下鼠标右键,选择“检视”,打开 Chrome 开发者工具,从中就能看到动态网页加载后的完整架构。
取得网页结构后,进一步分析网页结构,下方的程序使用 Selenium 函数库的功能,抓取特定的网页元素或进行指定的动作。
from selenium import webdriver
driver = webdriver.Chrome('./chromedriver')
driver.get('爬取的網址')
# 從載入後的動態網頁裡,找到指定的元素
imgCount = driver.find_element(By.CSS_SELECTOR, 'CSS 選擇器')
判断用户行为
针对“加入用户行为判断”的网页,确认页面加入的用户行为,就能模拟并进行破解,举例来说,有些网页会在按钮加上“鼠标碰触”的保护,如果不是真的用鼠标碰触,只是用程序撰写“点击”指令,就会被当作爬虫而被阻挡。
下方的程序使用 Selenium 函数库的功能,模拟出先碰触元素,再进行点击的动作,借此突破这个反爬虫的机制。
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
submitBtn = driver.find_element(By.CSS_SELECTOR, '#submitBtn')
actions = ActionChains(driver)
# 滑鼠先移到 submitBtn 上,然後再點擊 submitBtn
actions.move_to_element(submitBtn).click(submitBtn)
actions.perform()
有些网页也会判断用户刷新网页的时间 ( 通常用户不会在极短的时间内连续刷新 ),这时也可以使用 time 函数库的 sleep 方法让网页有所等待,避开这个检查机制
from selenium import webdriver
from time import sleep
submitBtn = driver.find_element(By.CSS_SELECTOR, '#submitBtn')
sleep(1) # 等待一秒
submitBtn.click()
sleep(0.5) # 等待 0.5 秒
submitBtn.click()
提交用户授权
针对“模拟真实用户登录授权”的网页,只要知道 request 与 response 的机制后,取得 Cookie 内的 token 就能破解。举例来说,下图为 Ptt 八卦版网页,从 Chrome 开发者工具里可以看到所需要的 Cookies 信息。
知道所需的 cookies 信息后,就能在 Requests 函数库里,增加相对应的信息,就能顺利爬取到数据。
import requests
cookies = {'over18':'1'}
# 加入 Cookies 資訊
web = requests.get('https://www.ptt.cc/bbs/Gossiping/index.html', cookies=cookies)
print(web.text)
破解验证码
针对“加入验证码机制”的网页,必须搭配一些 AI 来处理图形、数字、文字的识别,通常只要能识别验证码就能破解。如果要破解一般验证码,需要先将网页上的验证码图片下载,再将图片提交到 2Captcha 服务来帮我们进行辨识,等同于执行两次爬虫,先爬取目标网页,在爬取 2Captcha 网页取得辨识后的验证码,最后再把验证把输入目标网页。
因为步骤较为繁复,会用另外的篇幅介绍,此处仅介绍相关的原理。
2Captcha 服务:https://2captcha.com/
破解代理服务器与第三方 IP 封锁
针对“封锁代理服务器与第三方 IP”的网页,通常必须更换 IP 或更换代理服务器才能破解,许多网站上也有提供免费的 Proxy IP,以 Free Proxy List 网站为例,就能取得许多免费的 Proxy IP。
Free Proxy List:https://free-proxy-list.net/
下方的程序码会透过代理服务器 IP 的方式,执行 requests 函数库的 get 方法,如果该 IP 已经无法使用,就会出现 invalid 的提示。
import requests
# 建立 Proxy List
proxy_ips = ['80.93.213.213:3136',
'191.241.226.230:53281',
'207.47.68.58:21231',
'176.241.95.85:48700'
]
# 依序執行 get 方法
for ip in proxy_ips:
try:
result = requests.get('https://www.google.com', proxies={'http': 'ip', 'https': ip})
print(result.text)
except:
print(f"{ip} invalid")
小结
其实反爬虫的机制非常的多变 ( 甚至有些还会用一问一答的方式 ),不过也有很多网站没有加上反爬虫的保护,甚至直接提供了 API 的方式来让爬虫获取数据,总而言之,如果有 API 就直接取用,如果没有 API 又遇上反爬虫,就只能针对反爬虫的机制,采取对应的措施了。
微信扫码关注
抖音扫码关注