selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。
selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。
准备工作
安装Selenium:
pip install selenium
安装chromedriver:到http://chromedriver.storage.googleapis.com/index.html中下载跟自己Chrome版本匹配的驱动。
新建爬虫
scrapy startproject zhihu_selenium
cd zhihu_selenium
scrapy genspider zhihu www.zhihu.com
使用selenium模拟用户操作
先放上完整的爬虫程序:
# -*- coding: utf-8 -*-
import scrapy
import json
import time
from selenium import webdriver
from pathlib import Path
class ZhihuSpider(scrapy.Spider):
name = 'zhihu'
allowed_domains = ['www.zhihu.com']
start_urls = ['http://www.zhihu.com/']
# 模拟请求的headers
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.72",
"HOST": "www.zhihu.com"
}
# scrapy请求的开始时start_request
def start_requests(self):
zhihu_findUrl = 'https://www.zhihu.com/people/edit'
if not Path('zhihuCookies.json').exists():
self.loginZhihu() # 先执行login,保存cookies之后便可以免登录操作
# 毕竟每次执行都要登录还是挺麻烦的,我们要充分利用cookies的作用
# 从文件中获取保存的cookies
with open('zhihuCookies.json', 'r', encoding='utf-8') as f:
listcookies = json.loads(f.read()) # 获取cookies
# 把获取的cookies处理成dict类型
cookies_dict = dict()
for cookie in listcookies:
# 在保存成dict时,我们其实只要cookies中的name和value,而domain等其他都可以不要
cookies_dict[cookie['name']] = cookie['value']
# Scrapy发起其他页面请求时,带上cookies=cookies_dict即可,同时记得带上header值,
yield scrapy.Request(url=zhihu_findUrl, cookies=cookies_dict, callback=self.parse, headers=self.headers)
def parse(self, response):
# 打印出设置页面中登录者的昵称
print("*" * 40)
print(response.xpath('//span[@class="FullnameField-name"]/text()').extract_first())
print("*" * 40)
# print("response text: %s" % response.text)
# print("response headers: %s" % response.headers)
# print("response meta: %s" % response.meta)
# print("request headers: %s" % response.request.headers)
# print("request cookies: %s" % response.request.cookies)
# print("request meta: %s" % response.request.meta)
# 使用selenium登录知乎并获取登录后的cookies,后续需要登录的操作都可以利用cookies
@staticmethod
def loginZhihu():
# 登录网址
loginurl = 'https://www.zhihu.com/signin'
# 加载webdriver驱动,用于获取登录页面标签属性
driver = webdriver.Chrome('D:/Software/chromedriver.exe')
# 加载页面
driver.get(loginurl)
time.sleep(3) # 执行休眠3s等待浏览器的加载
# 方式1 通过填充用户名和密码
# driver.find_element_by_name('username').clear() # 获取用户名框
# driver.find_element_by_name('username').send_keys(u'username') # 填充用户名
# driver.find_element_by_name('password').clear() # 获取密码框
# driver.find_element_by_name('password').send_keys(u'password') # 填充密码
# input("检查网页是否有验证码要输入,有就在网页输入验证码,输入完后,控制台回车;如果无验证码,则直接回车")
# # 点击登录按钮,有时候知乎会在输入密码后弹出验证码,这一步之后人工校验
# driver.find_element_by_css_selector("button[class='Button SignFlow-submitButton Button--primary Button--blue']").click()
#
# input_no = input("检查网页是否有验证码要输入,有就在网页输入验证码,输入完后,控制台输入1回车;如果无验证码,则直接回车")
# if int(input_no) == 1:
# # 点击登录按钮
# driver.find_element_by_css_selector(
# "button[class='Button SignFlow-submitButton Button--primary Button--blue']").click()
# 方式2 直接通过扫描二维码,如果不是要求全自动化,建议用这个,非常直接,毕竟我们这一步只是想保存登录后的cookies,至于用何种方式登录,可以不必过于计较
driver.find_element_by_css_selector("div[class='SignFlow-qrcodeTab']").click()
input("请扫描页面二维码,并确认登录后,点击回车:") # 点击二维码手机扫描登录
time.sleep(3) # 同样休眠3s等待登录完成
input("检查网页是否有完成登录跳转,如果完成则直接回车")
# 通过上述的方式实现登录后,其实我们的cookies在浏览器中已经有了,我们要做的就是获取
cookies = driver.get_cookies() # Selenium为我们提供了get_cookies来获取登录cookies
driver.close() # 获取cookies便可以关闭浏览器
# 然后的关键就是保存cookies,之后请求从文件中读取cookies就可以省去每次都要登录一次的
# 当然可以把cookies返回回去,但是之后的每次请求都要先执行一次login没有发挥cookies的作用
jsonCookies = json.dumps(cookies) # 通过json将cookies写入文件
with open('zhihuCookies.json', 'w') as f:
f.write(jsonCookies)
print(cookies)
执行爬虫程序,第一次执行的时候,selenium会自动打开浏览器,模拟用户点击,用户登录后,获取到cookies,存储到zhihuCookies.json
文件中。
以后执行,程序都将从zhihuCookies.json
文件中读取cookies,执行后续操作,这里,我们获取知乎用户信息编辑页面中的用户名:
至此,一个模拟用户操作浏览器的爬虫程序就完成了。