近日有一个小练习,要从XXX网站上爬取特定的查询结果(仅是练习爬虫,没有任何其他用意~~)。兴冲冲的就拿来selenium开始上手。不料出师不利,屡遭挫折,历经了很长一段时间的suffer后,最终也是功亏一篑。
这时才知道,这个网站有过被爬虫师傅爬崩掉的一段不堪回首的往事,已经做了很高级的反爬。到底高不高级不清楚,但对我这个小白来说也是一座不是那么容易翻过的高山了。
但回首自己的尝试,又感到有点神奇。故记录一下自己的经历,以供未来参考。欢迎大佬指点迷津。
本文以笔者尝试爬取xxx网站的过程为线,介绍笔者在使用selenium对该网站进行爬取的每一步的操作与遇到的问题。
使用:python,版本3.9,chrome浏览器,版本101.0,selenium版本4.1.3
首先提一下一些普遍的问题,第一点,这个网站的不稳定性,我在手动操作该网站的时候,就遇到过网站返回信息不全面的情况(有时候是登录界面找不到输入框。。。),还有的时候会加载超时,本来以为用IE会好一点,结果也有类似的情况出现,介于IE上能找到的资料也少,还不如chrome方便,于是就决定继续用chrome了。
还有一个问题是,这个网站在打开开发者工具时会进行无限debugger,阻止你对网站进行调试。可以通过chrome的禁用断点调试功能来处理。
如果某一个时间段内登录的次数过多,这个网站还会有验证码环节。
首先就要用selenium来打开这个网站。代码如下:
import time,json
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
if __name__ =='__main__':
s = Service("./chromedriver.exe")
bro = webdriver.Chrome(service=s)
bro.get('https://......./')
#bro.close()
运行一看,能进入,于是使用selenium去点击登录按钮,以进入登录界面,
if __name__ =='__main__':
s = Service("./chromedriver.exe")
bro = webdriver.Chrome(service=s)
bro.get('https://......./')
bro.maximize_window()
time.sleep(10)
login = bro.find_element(By.XPATH, '//*[@id="loginLi"]/a')
login.click()
#bro.close()
然后就,非常愉快的返回了400。。。
身为小白的博主便去问度娘,度娘说,可能是浏览器被反爬虫程序识别了,它会检查你的window .navigator .webdriver属性,正常用户登录都是false或undefined,而用selenium就会变成true,我一看,果然是这个样子,于是按度娘说的改了代码。
if __name__ =='__main__':
s = Service("./chromedriver.exe")
chrome_options = Options()
chrome_options.add_argument(
'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
bro = webdriver.Chrome(service=s,options=chrome_options)
bro.get('https://......./')
bro.maximize_window()
time.sleep(10)
login = bro.find_element(By.XPATH, '//*[@id="loginLi"]/a')
login.click()
#bro.close()
再次运行,又很愉快的再次返回400。。。
看了下 window .navigator .webdriver,已经变成false了。
博主见到这种情况很不知所措,急忙又去问度娘,只见度娘缓缓答道:“清一下cookie试试”。博主立刻遵旨,将代码改成了这样:
if __name__ =='__main__':
s = Service("./chromedriver.exe")
chrome_options = Options()
chrome_options.add_argument(
'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
bro = webdriver.Chrome(service=s,options=chrome_options)
bro.get('https://......./')
bro.maximize_window()
time.sleep(10)
login = bro.find_element(By.XPATH, '//*[@id="loginLi"]/a')
#这一步删掉了所有的cookie
bro.delete_all_cookies()
login.click()
#bro.close()
奇迹,发生了,我成功的进入了登录界面。
所以就连忙用selenium找到相应的输入框输入账号密码,然后点击登录,成功进入登录后的界面(虽然不知道这次为什么可以不用删除cookie)
然后就是用selenium在搜索框中输入相应的搜索条件,再点击搜索,然后。。。相同的问题又出现了。
然而这次不能再像上次一样直接删除所有的cookie了,因为博主这样干了一次后发现博主的登录信息也被删掉了,网站直接回到了登录界面,这就令人非常的难受。
if __name__ =='__main__':
s = Service("./chromedriver.exe")
chrome_options = Options()
chrome_options.add_argument(
'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
bro = webdriver.Chrome(service=s,options=chrome_options)
bro.get('https://......./')
bro.maximize_window()
time.sleep(10)
login = bro.find_element(By.XPATH, '//*[@id="loginLi"]/a')
bro.delete_all_cookies()
login.click()
bro.refresh()
time.sleep(10)
bro.switch_to.frame('contentIframe')
phonum = bro.find_element(By.XPATH, '//*[@id="root"]/div/form/div/div[1]/div/div/div/input')
key = bro.find_element(By.XPATH, '//*[@id="root"]/div/form/div/div[2]/div/div/div/input')
btn = bro.find_element(By.XPATH, '//*[@id="root"]/div/form/div/div[3]/span')
phonum.send_keys('请输入您的手机号')
key.send_keys('请输入您的密码')
btn.click()
time.sleep(3)
bro.switch_to.default_content()
time.sleep(3)
btn1 = bro.find_element(By.XPATH, '//*[@id="_view_1540966814000"]/div/div[1]/div[1]')
btn1.click()
time.sleep(3)
input = bro.find_element(By.ID, 'qbValue')
input.send_keys('江苏广信感光新材料股份有限公司')
btn2 = bro.find_element(By.ID, 'searchBtn')
btn2.click()
#bro.close()
博主开始想,那cookie就不全不删掉了,就只删掉那些与登录无关的cookie是不是就行了?
于是博主保存了登录界面的cookie1与登录完成跳转后的页面的cookie2,分别如下:
这是登录页面中的cookie1:
[
{"domain": ".....", "expiry": 1667707332, "httpOnly": false, "name": "_bl_uid", "path": "/", "secure": false, "value": "......"}
,{"domain": "......", "expiry": 1667880132, "httpOnly": false, "name": "CNZZDATA1278108394", "path": "/", "secure": false, "value": "........"}
,{"domain": ".........", "expiry": 1667880132, "httpOnly": false, "name": "UM_distinctid", "path": "/", "secure": false, "value": "........."}
,{"domain": "........", "httpOnly": true, "name": "HOLDONKEY", "path": "/", "sameSite": "None", "secure": true, "value": "..........."}
]
这是登录后跳转到的页面的cookie2
[
{"domain": ".......", "expiry": 1967515347, "httpOnly": false, "name": "HM4hUBT0dDOn443T", "path": "/", "secure": true, "value": "......"}
,{"domain": "........", "httpOnly": true, "name": "SESSION", "path": "/", "secure": false, "value": "......."}
,{"domain": ".......", "expiry": 1667880132, "httpOnly": false, "name": "UM_distinctid", "path": "/", "secure": false, "value": "........."}
,{"domain": "........", "expiry": 1652155631, "httpOnly": true, "name": "wzws_reurl", "path": "/", "secure": false, "value": "........"}
,{"domain": "..........", "expiry": 1967515251, "httpOnly": true, "name": "HM4hUBT0dDOn443S", "path": "/", "secure": true, "value": "......."}
]
可以看出两个页面的cookie中有一个名为UM_distinctid的cookie是不变的,应该是与用户登录有关的信息,还有一个session的cookie应该也是不能删的。
于是博主就顺着这个思路删掉了cookie2中的其他三个cookie:
if __name__ =='__main__':
s = Service("./chromedriver.exe")
chrome_options = Options()
chrome_options.add_argument(
'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
bro = webdriver.Chrome(service=s,options=chrome_options)
bro.get('https://......./')
bro.maximize_window()
time.sleep(10)
login = bro.find_element(By.XPATH, '//*[@id="loginLi"]/a')
bro.delete_all_cookies()
login.click()
bro.refresh()
time.sleep(10)
bro.switch_to.frame('contentIframe')
phonum = bro.find_element(By.XPATH, '//*[@id="root"]/div/form/div/div[1]/div/div/div/input')
key = bro.find_element(By.XPATH, '//*[@id="root"]/div/form/div/div[2]/div/div/div/input')
btn = bro.find_element(By.XPATH, '//*[@id="root"]/div/form/div/div[3]/span')
phonum.send_keys('请输入您的手机号')
key.send_keys('请输入您的密码')
btn.click()
time.sleep(3)
bro.switch_to.default_content()
time.sleep(3)
btn1 = bro.find_element(By.XPATH, '//*[@id="_view_1540966814000"]/div/div[1]/div[1]')
btn1.click()
time.sleep(3)
input = bro.find_element(By.ID, 'qbValue')
input.send_keys('江苏广信感光新材料股份有限公司')
btn2 = bro.find_element(By.ID, 'searchBtn')
#这里删除多余的cookie
bro.delete_cookie('HM4hUBT0dDOn443T')
bro.delete_cookie('wzws_reurl')
bro.delete_cookie('HM4hUBT0dDOn443S')
btn2.click()
#bro.close()
奇迹又发生了,我成功的进入到了查询结果的界面中!!!
但博主的任务还没有完成,因为查询的结果有很多页,博主希望能查询到每一页的结果,于是就非常激动的用selenium找到翻页的按钮,结果。。。。熟悉的问题又回来了。翻页的js请求得到了服务器400的响应。
借助之前成功的经验,博主企图在cookie上在动手脚来获取正常的响应,无奈几经尝试,多次与手动操作进行比较后无果。最后又参考了网上的许多博客上的方法也没有得到解决,只得作罢,将过程记录于此。
个人学习笔记,如需转载请注明出处。