pyppeteer 开发记录

不管怎么对 selenium 的 webdriver 标识进行防御,selenium 爬取还是被识别了。。原因是 selenium 唤起浏览器需要通过 chromedriver.exe / geckodriver.exe 来唤起 谷歌 / 火狐,恰恰就是这些驱动导致 selenium 被识别,好家伙,反爬直接给你釜底抽薪了。网上也有去掉 webdriver 标识并反编译的 chromedriver.exe,但对于拿来党来说,系统环境、版本限制太大了,又不想花时间去搞这个反编译,就去找哪个能代替 selenium。福音来了~ puppeteer 简直就是为 chrome 浏览器自动化测试量身打造啊~~ pyppeteer 就是 python 版的 puppeteer。

安装和部署 pyppeteer 的教程网上有,这里不多说。

废话不多说,直接上 pyppeteer 的 scrapy 应用吧~

import pyppeteer
import asyncio
import logging
import random
import json
pyppeteer_level = logging.WARNING
logging.getLogger('pyppeteer').setLevel(pyppeteer_level)
logging.getLogger('websockets.protocol').setLevel(pyppeteer_level)
pyppeteer_logger = logging.getLogger('pyppeteer')
pyppeteer_logger.setLevel(logging.WARNING)
# 以上	代码作用是除了WARNING报错,浏览器操作就不显示在控制台了,控制台清爽多了~~
pyppeteer.DEBUG = False
# 一定一定要加下面代码,否则还是会反爬被识别出是自动化测试的
pyppeteer.launcher.AUTOMATION_ARGS.remove("--enable-automation")

class ProxyMiddleware(object):
    def random_region(self, start, end):
        return int(random.uniform(start, end) * 1000)

    async def use_pptr(self, request, ip):
        res, _ua = ({'state': False}, '')
        try:
            settings = get_project_settings()
            driver = await pyppeteer.launch(
                {'executablePath': settings.get('CHROME_PATH'), 'userDataDir': settings.get('USER_DATA_PATH'),
                 'headless': False, 'dumpio': True, 'autoClose': False,
                 'args': ['--no-sandbox', '--disable-extensions', '--disable-dev-shm-usage', '--disable-setuid-sandbox',
                          '--incognito', '--disable-infobars', '--disable-gpu', '--disable-popup-blocking',
                          '--ignore-certificate-error', '--mute-audio', '--user-agent=' + _ua, '--proxy-server=' + ip]})
            page = (await driver.pages())[0]	# 这样就不用非得newPage才能goto了,对于隐私模式来说,用newPage,之前launch设置的浏览器配置就全没了
        except Exception as e:
            print('浏览器创建失败,重新请求')
            print(e)
            return res
        try:
            await page.goto(request.url, {'waitUntil': 'networkidle2'})
            await page.waitFor(self.random_region(2, 4))
            query = await page.waitForSelector('#xxx div a')
            await query.click()		# 元素点击
            input = await page.waitForSelector('.xxx')
            await input.focus()		# 元素焦点获取
            await input_into.type(str(request.meta['xxx']))	# 输入内容
            search = await page.waitForSelector('#xxx')
            await search.click()        # 提交查询
            await page.waitFor(self.random_region(2, 3))     # 等待2-3秒,等待新窗口打开
            page1 = (await driver.pages())[1]	# 新页面
            link_a = await page1.waitForXPath('//xxx')
            ele = await page1.Jeval('.xxx', 'el=> el.getAttribute(\'id\')')	# 获取指定元素的指定id属性值
            res = {'state': True, 'data': json.dumps(await page1.content())	# 页面源码
                pass
        except Exception as e:
            print(e)
        finally:
            await page.waitFor(1000)	# 关闭浏览器前一定要有个等待缓冲时间,否则有时会报错哦
            await driver.close()
        return res.

def process_request(self, request, spider):
	ip_info = 'http://xxx.xxx.xxx.xxx'
	task = asyncio.ensure_future(self.use_pptr(request, ip_info))
    asyncio.get_event_loop().run_until_complete(task)
    result = task.result()
    return HtmlResponse(url=request.url, body=result['data'], request=request, encoding='utf-8', status=200) if result['state'] else HtmlResponse(url=request.url, status=400, request=request)

目标网站服务器维护不易,让我们自觉放慢爬取脚步吧,不让爬虫给服务器太大压力哦~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值