scrapy整合selenium
1. 基本介绍
selenium在解决js动态加载以及反爬虫措施比较多的网站有奇效,将其整合scrapy可以大大提高我们爬取的效率
2. 代码编写
2.1 spider类
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def __init__(self):
chrome_options = Options()
# chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
self.browser = webdriver.Chrome(chrome_options=chrome_options)
self.browser.implicitly_wait(10)
self.browser.set_page_load_timeout(10)
super(SpscSpider, self).__init__()
dispatcher.connect(self.closeSpider, signals.spider_closed)
def closeSpider(self, spider):
print("spider closed")
# 当爬虫退出的时关闭浏览器
self.browser.quit()
将浏览器设置为spider 的一个属性,在初始化的时候创建,则所有的spider都可以共享这一个浏览器,不必重复创建
2.2 middleware
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
class SeleniumMiddleware(object):
def process_request(self, request, spider):
if spider.name == "spsc":
while True:
try:
spider.browser.get(request.url)
break
# 报错以后重新生成一个浏览器访问该链接
except:
spider.browser.close()
spider.browser.quit()
chrome_options = Options()
# chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
spider.browser = webdriver.Chrome(chrome_options=chrome_options)
spider.browser.implicitly_wait(10)
spider.browser.set_page_load_timeout(10)
continue
time.sleep(1)
return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source,encoding="utf-8", request=request)
- 这里利用一个下载中间件,这个中间件调用的顺序位于spider和download之间,即spider初始化以后,收到访问请求,然后经过下载中间件,即经过这个类
- 上面的一个while循环的作用是,如果浏览器访问失败,那么整个程序就会卡住,为了防止这种情况,利用try except,如果访问失败,那么重新生成一个spider的浏览器,重新访问这个链接,直到访问成功。
- return了一个HtmlResponse,这个的作用是使scrapy不经过下载器直接返回页面到spider,这里url就是浏览器的当前url,body就是浏览器的页面page_source
- 这样就把selenium嵌入到scrapy当中
2.3 settings
DOWNLOADER_MIDDLEWARES = {
'spsc.middlewares.SpscDownloaderMiddleware': 543,
'spsc.middlewares.MyUserAgentMiddleware': 400,
'spsc.middlewares.SeleniumMiddleware': 540
}
设置中打开下载中间件
3. 不足
使用selenium会将scrapy从异步变成同步,效率上会大打折扣。解决这个问题需要重写scrapy的download,比较复杂,日后研究