最近反爬越来越严重啦~有些网站有心跳函数,破js还不如直接上selenium搞数据~
但如果大部分其他网站还是用scrapy的管道处理数据的话,单纯用selenium,就代表又要把管道删删改改丢到selenium的脚本中....
太麻烦了我拒绝!
其实可以用scrapy的中间件包裹selenium中的网页源码,丢回scrapy程序中采集~
相当于只是把selenium当做中间件工具一样使用~
话不多说直接上代码~
先把用浏览器打开网页的jio本写好~
1.操纵浏览器的selenium_chrome.py
#! /usr/bin/env python3# coding=utf-8from selenium import webdriverimport requestsimport sysimport timesys.path.append("./")import randomfrom fake_useragent import UserAgentfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.ui import WebDriverWait #WebDriverWait注意大小写from selenium.webdriver.common.by import Byclass Chrome_selenium(object): '''开启无头浏览器''' def __init__(self): self.chrome_options = webdriver.ChromeOptions() # 看情况是显示界面 or无头模式。本地调试时可以开启界面看一下~ # linux服务器上只能用无头模式 self.chrome_options.add_argument('--headless') self.chrome_options.add_argument('--no-sandbox') self.chrome_options.add_argument('--disable-gpu') # #https证书 self.chrome_options.add_argument('--ignore-certificate-errors') # self.chrome_options.debugger_address = "127.0.0.1:9222" #test self.chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) # chrome_driver = "/usr/bin/google-chrome" # #设置请求头 self.chrome_options.add_argument(UserAgent(verify_ssl=False).random) # 不需要图片和js的话可以把下面的注释打开~ # prefs = { # 'profile.default_content_setting_values': { # 'images': 2, # 屏蔽图片 # 'javascript': 2, # 屏蔽js # 'notifications': 2, # 屏蔽消息推送 # } # } # # 添加屏蔽chrome浏览器禁用图片的设置 # self.chrome_options.add_experimental_option("prefs", prefs) #test # self.chrome_options.debugger_address = "127.0.0.1:9210" self.client = webdriver.Chrome(options=self.chrome_options) # # # 隐性等待 # self.client.implicitly_wait(30) # # timeout # self.client.set_page_load_timeout(30) #时间看加载情况~ # # 隐性等待 self.client.implicitly_wait(120) # timeout self.client.set_page_load_timeout(160) # # 窗口最大化 self.client.maximize_window() def get_one_page(self, one_html_url): '''获取one page的源码''' try: self.client.get(one_html_url) # self.client.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 需要滚动到底部 或者点击 滑动之类动作的话,就用if根据网址规则来进行操作 if "www.zzzzz.com" in one_html_url: # 执行这段代码,会获取到当前窗口总高度 js = "return action=document.body.scrollHeight" # 初始化现在滚动条所在高度为0 height = 0 # 当前窗口总高度 new_height = self.client.execute_script(js) while height < new_height: # 将滚动条调整至页面底部 for i in range(height, new_height, 100): self.client.execute_script('window.scrollTo(0, {})'.format(i)) time.sleep(0.5) height = new_height time.sleep(2) new_height = self.client.execute_script(js) elif 'www.xxxxxx.com' in one_html_url: # 等指定的元素加载完毕后,再 if '/cat' in one_html_url: try: element = WebDriverWait(self.client, 10).until(EC.presence_of_element_located((By.XPATH, '//div[@data-pagination-start]'))) # print(f'element:{element}') except Exception as message: print('元素定位报错%s' % message) finally: pass elif 'xxxxx.desktop.json' not in one_html_url: #//h2[contains(text(),"Details")] try: element = WebDriverWait(self.client, 10).until(EC.presence_of_element_located((By.XPATH, '//div[contains(@class,"horizontalSlider")]'))) # print(f'element:{element}') except Exception as message: print('元素定位报错%s' % message) finally: pass # 超时就直接返回源码 except Exception as e: print('client error:{}'.format(e)) # self.client.refresh() return self.client.page_source current_page_html = self.client.page_source return current_page_html
2.scrapy工程中的middlewares.py
...# 导入操作浏览器的脚本from selenium_chrome import Chrome_selenium# 用HtmlResponse封装源码from scrapy.http import HtmlResponse......class Seleniummiddleware(object): def __init__(self): self.chrome_selenium = Chrome_selenium() self.request_session = requests.Session() def process_request(self, request, spider): if 'www.zzzz.com' in request.url: one_list_page_source = self.chrome_selenium.get_one_page(request.url) # time.sleep(30) # 等待加载, 可以用显示等待来优化. # print(f'one_list_page_source:{one_list_page_source}') # 参数url指当前浏览器访问的url, 在这里参数url也可以用request.url # 参数body指要封装成符合HTTP协议的源数据, 后两个参数可有可无 return HtmlResponse(url=request.url, body=one_list_page_source, encoding='utf-8', request=request)
这样搞完后,在scrapy的爬虫代码文件中,就可以和普通的爬虫response一样使用xpath函数来取值了~
一定要记得在爬虫代码中开启selenium的中间件~
搞完收工~