更多优质内容
请关注公众号

爬虫进阶之Scrapy(七) 使用selenium模拟浏览器动态爬取-阿沛IT博客

正文内容

爬虫进阶之Scrapy(七) 使用selenium模拟浏览器动态爬取

栏目:Python 系列:scrapy爬虫系列 发布时间:2019-12-26 16:50 浏览量:8376

续上一章 scrapy中的反反爬虫技术


使用selenium模块进行动态爬取

有一些网站的内容是通过js动态加载的,例如使用ajax请求,这样动态加载的内容无法出现在源代码中,我们就无法获取到这部分内容。有时候,这是因为业务逻辑的需求要使用 js 动态加载,但是有时候也是因为防止爬虫而使用 js 加载。

selenium的原理是模仿浏览器访问页面,将动态加载的内容也渲染到页面时候,再获取渲染好的页面代码。从而解决这个问题。


selenium 动态抓取
selenium的基本原理是操作浏览器,selenium支持ie,火狐,谷歌等浏览器,所以对于每一种浏览器,他都有一个driver驱动。

selenium 的安装:
首先在Python安装:


pip install selenium

然后你还要下载相应的浏览器,比如谷歌
那么你要下载谷歌浏览器
同时还要下载谷歌浏览器的driver,没有这个driver就无法再Python中用selenium操作谷歌浏览器。
这个driver是一个exe文件

先百度搜索selenium python api
它里面有selenimu的文档
再在文档找chrome webdriver

他有个链接:http://chromedriver.storage.googleapis.com/index.html
用来下载谷歌浏览器的driver(驱动),这个driver的作用是让selenium控制谷歌浏览器

我们要先在自己的电脑上找到谷歌浏览器的所在安装目录查看版本,再下载相应版本的driver


当你已经下载了这个driver,假如在d盘的D:/chromedriver.exe

from selenium import webdriver

url = "https://www.baidu.com"
browser = webdriver.Chrome(executable_path="D:/chromedriver.exe")
browser.get(url)
print(browser.page_source)

browser.quit()  #退出浏览器

这是最简单的一个例子,在运行这段代码的时候,浏览器会自己弹出来,当运行到browser.quit()的时候,浏览器会关闭。


接下来介绍selenium的其他简单用法:

selenium的输入和点击操作:
接下来,使用selenimu登陆知乎
输入用send_keys()方法
点击用click()方法

# coding = utf-8

from selenium import webdriver

url = "https://www.zhihu.com/signin"

browser = webdriver.Chrome(executable_path="D:/chromedriver.exe")

browser.get(url)

browser.find_element_by_xpath("//input[@name='username']").send_keys("你的知乎账号")
browser.find_element_by_xpath("//input[@name='password']").send_keys("你的知乎密码")
browser.find_element_by_xpath("//form[@class='SignFlow']/button[@type='submit']").click()


PS:一定要先调用get方法才可以用find_element_by_xpath来查找元素


有时候使用selenium获取元素是会报错说找不到某元素,这可能是因为页面还会在加载。
此时我们可以在get方法和find_elementby_xpath之间用一个
time.sleep(2)
睡两秒先。

接下来我们介绍一下如何下滑鼠标:

browser.execute_script("window.scrollTo(0,document.body.scrollHeight);")

上面的意思是,执行js语句让他下拉鼠标。


设置chromdriver不加载图片:

opt = webdriver.ChromeOptions()
prefs = {"profile.managed_default_content_settings.images":2}
opt.add_experimental_option(prefs)
browser = webdriver.Chrome(executable="xxx",chrome_options=opt)
webdriver.get("https://www.taobao.com")


这是一种很固定的写法
不加载图片可以在爬取的时候加速加载页面

设置了不加载图片,但是页面内容中的img标签并没有消失,所以你依旧可以获取到img中的src


使用selenimu获取cookie信息并存到文件中:
以登陆tswq8为例子

# -*- coding: utf-8 -*-
from selenium import webdriver
import time

driver = webdriver.Chrome(executable_path="d:/chromedriver.exe")

driver.get("https://www.tswq8.com/login")

time.sleep(30)  #这30秒时间是你手动在浏览器上登陆

cookie_items = driver.get_cookies()   #此时你已经登陆完了,页面跳转到首页

#它返回的cookie信息是一个列表放着多个字典
#我们知道header头中的cookie数据是一堆字符串,类似于:
#Cookie:a=1;b=2;c=3
#get_cookies()返回的数据就类似:
#[{'domain': 'www.tswq8.com', 'expiry': 1567418151.823395, 'httpOnly': False, 'name': 'a', 'path': '/', 'secure': False, 'value': '1'}, {'domain': 'www.tswq8.com', 'expiry': 1567418151.823346, 'httpOnly': False, 'name': 'b', 'path': '/', 'secure': False, 'value': '2'}, {'domain': 'www.tswq8.com', 'httpOnly': True, 'name': 'c', 'path': '/', 'secure': False, 'value': '3'}]
#我们只要将每个字典里的 name和value 取出来组成字符串就可以变成a=1;b=2;c=3的形式

#将cookie信息存入文件中:
cookie_str = ""
for i in cookie_items:
	cookie_str = cookie_str + i['name']+"="+i['value']+";"
	
with open("cookie.txt","w",encoding="utf-8") as f:
	f.write(cookie_str)


怎么在selenium请求的时候加上header:

要使用add_argument()

headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
    "Host":"mp.weixin.qq.com"
}

#先获取chromeOptions
options = webdriver.ChromeOptions()

#为selenium的请求添加header
options.add_argument('user-agent='+headers['User-Agent'])
options.add_argument('host=' + headers['Host'])

#再实例化谷歌浏览器驱动,在实例化的时候传入options
driver = webdriver.Chrome(executable_path="d:/chromedriver.exe",chrome_options=options)
driver.get(url)


将selenium集成到scrapy中:

使用中间件:

class JSPageMiddleware(object):
	def __init__(self):
		super(JSPageMiddleware,self).__init__()
		self.browser = webdriver.Chrome(executable_path="xxx")
		
	def process_request(self,request,spider):
		#在正常使用中,可能只对部分url进行动态加载,所以或使用正则来判断
		browser.get(request.url)
		time.sleep(1)
		
		#在这里我们不能return None,如果return None,那么请求会被发送到下载中间件去下载这个页面,在将这个页面的response返回给spider。但是我们上面browser.get的时候就已经下载了这个页面的内容,所以没有必要在下载一次,我们只要制定一个response对象,直接返回这个response给蜘蛛即可
		return scrapy.HtmlResponse(url=browser.current_url,body=browser.page_source,encoding="utf-8",request=request)   #这4个参数必须有


如果使用selenium动态获取页面,那么多线程的爬虫会变成单线程的,降低效率。


在Linux中使用selenium的时候,我们要对selenium加几条配置,否则很可能会出现报错

chrome_options = Options()
chrome_options.add_argument('--headless')    #无头浏览器
chrome_options.add_argument('--disable-gpu')
browser = webdriver.Chrome(executable_path=path, chrome_options=chrome_options)






更多内容请关注微信公众号
zbpblog微信公众号

如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > 爬虫进阶之Scrapy(七) 使用selenium模拟浏览器动态爬取

热门推荐
推荐新闻