基于[pypyeteer] 的脚本开发记录

随着技术的发展,selenium的识别技术越发成熟,selenium在爬虫和脚本的适用性开始下降,一般适用于反爬程度相对低的动态网页的渲染,并且api加密,需要快速开发的爬虫项目.
目前所接触到selenium被识别的网站有,淘宝,新浪微博,lazada.被识别的效果是怎么样的?
淘宝和lazada类似[同一个老板的网站],登录的滑动条,无论多精确的js定位识别动作,或者是伴随手动,都是无法通过这个滑动条的验证的.
新浪微博418返回.

如何解决这些问题?网上给出的方法很多,解决的思路方向也很多.查询到的主要说法,selenium特征值的检测,说的最多的一个就是

# F12 进入console
window.navigator.webdriver   # 回车
#正常返回值是 false/undefined
#驱动器驱动的话则返回true

当然还有许多的检测方法,基于其他特征值的检查
具体原理详细问度娘.

  1. 测试过的方法也不少,
      a)selenium的window.navigator.webdriver手动修改,只能修改一次,网页刷新后特征值恢复,当然网上也有大神说可以做到持续修改这个特征值的办法,我还没测试成功,不仅仅由于时间问题.
      b)启动开发者模式,操作如下

    	options = webdriver.ChromeOptions()
        options.add_experimental_option('excludeSwitches', ['enable-automation'])
    

    该方法的最明显的体现是,启动chrome的时候,右上角会提示我们,建议我们关闭开发者模式
    ,自测评价:求个心安理得,甚至可能有反效果.
      c)爬虫项目可斟酌测试以上的方法,小平台一般无阻挡,电商平台以及一些数据用户信息比较多的社交类网站可能就会更加严格,甚至使用selenium无法跨越

  2. 以上问题迟到都要会遇到的,如果你是一名爬虫工.以下步入正题.
    pyppeteer的使用,百闻不如一见,看得厉害的模块再多不如自己亲手试一试.
    刚好最近在用pyppeteer开发小脚本,特做一下笔记.

引言:
github地址:https://miyakogi.github.io/pyppeteer/

pyppeteer这个项目是非官方的,是基于谷歌官方puppeteer的python版本。

注意:本来chrome就问题多多,puppeteer也是各种坑,加上pyppeteer是基于前者的改编python版本,也就是产生了只要前两个有一个有bug,那么pyppeteer就会原封不动的继承下来,本来这没什么,但是现在遇到的问题就是pyppeteer这个项目从18年9月份之后就没更新过了,前两者都在不断的更新迭代,而pyppeteer一直不更新,导致很多bug根本没人修复。

这个模块的使用加入了异步,习惯一般python代码的风格,一开始有点难适应.
  1. pyppeteer是搭配chronium使用的,安装流程自动百度
    启动[包括脚本和爬虫的中一些常用的操作,在以下注释]:
import pyppeteer
from pyppeteer import launch
import asyncio

# 浏览器初始值参数设置
async def create_page():
    screenWidth, screenHeight = pyautogui.size()
    browser = await launch({
        'headless': False, #无头模式关闭
        'dumpio': True,
        'autoClose': False,
        'args': ['--disable-infobars',
                 '--window-size=%s,%s'%(screenWidth,screenHeight), #设置窗口大小
                 # '--no-sandbox',
                 # '--proxy-server=127.0.0.1:1080'
                 ]
    })
    page = await browser.newPage()

    await page.setViewport({'width': screenWidth, 'height': screenHeight})#窗口中显示网页的窗口大小
    #设置请求头
    await page.setUserAgent(random.choice(user_agent_one))

    return browser, page


async def main(page):
    # 持久修改特征值,也就是navigator.webdriver
    # 此步参考来源 https://blog.csdn.net/weixin_41624982/article/details/89668879
    await page.evaluateOnNewDocument('() =>{ Object.defineProperties(navigator,'
                                     '{ webdriver:{ get: () => false } }) }')
    # 加载目标网站
   	# 设置目标网站,超时时间
    await page.goto('https://sellercenter.lazada.co.id/im/window',{'timeout': 1000*360})
    # xpath匹配式,顾名思义,等待该节点的加载
    await page.waitForXPath("//input[@name='TPL_username']")	
    
	# 输入文字,选取按照selector去定位元素,并且输入指定文本
    input_sjh = await page.xpath("//input[@name='TPL_username']")
    await input_sjh[0].type('指定文本')
	
	# 点击操作
	click_yzm = await page.xpath("//button[@class='next-btn next-btn-normal next-btn-medium btn']")
    await click_yzm[0].click()
    
   # page.xpath返回的对象是列表,里面的元素的类型是elmenthandle/jshandle,那么如何获取该elementhandle的文本呢?
   # **划重点!网上很难找到这个**
   # 适用场景,聊天好友列表,点击该好友,获取好友的名称做记录这样
   elementText = await (await friend_list[2].getProperty("innerHTML")).jsonValue()

   # 很多操作都可以基于js来对网页进行操作
   # 实例1: 滚动条'.scroll-content'向下,滚动1000px
   height=1000
   js="document.querySelector('.scroll-content').scrollTop=%s;"%height
   await page.evaluate(js)  #page.evaluateOnNewDocument(js)
   # 更多的操作可以仔细问问度娘+测试

   # put 一个网上看到的操作验证条的方法
   # 在lazada后台登录过程实现 拉满验证条
   # ps:拉验证条的过程中,最好是伴随着鼠标光标的移动,才可更高通过登录验证
async def try_validation(page, distance=392):
    # 将距离拆分成两段,模拟正常人的行为
    distance1 = distance - 10
    distance2 = 10
    while True:
        if await page.xpath("//span[@id='nc_1_n1z']"):
            break
        else:
            print("等待加载中...")
            await asyncio.sleep(1)
	
	# ID为nc_1_n1z的验证条
    btn_position = await page.evaluate('''
       () =>{
        return {
         x: document.querySelector('#nc_1_n1z').getBoundingClientRect().x,
         y: document.querySelector('#nc_1_n1z').getBoundingClientRect().y,
         width: document.querySelector('#nc_1_n1z').getBoundingClientRect().width,
         height: document.querySelector('#nc_1_n1z').getBoundingClientRect().height
         }}
        ''')

    # await print("获取定位成功")
    x = btn_position['x'] + btn_position['width'] / 2
    y = btn_position['y'] + btn_position['height'] / 2

    # await move_mouse(x,y) 自己写的方法,pyautogui模块
    # await print("获取定位成功",x,y)
    # print(btn_position)
    # 定位到滚动条的元素的位置
    await page.mouse.move(x, y)
    #鼠标按住
    await page.mouse.down()
    # ***在拉滚动条的时候,鼠标要移动,才不被识别出来***
    pyautogui.moveTo(x + 200, y + 100, duration=1)

    await page.mouse.move(x + distance1, y, {'steps': 30})
    await page.waitFor(800)

    await page.mouse.move(x + distance1 + distance2, y, {'steps': 20})
    await page.waitFor(800)
    # 鼠标放开
    await page.mouse.up()
   
# 关闭
async def close_page(browser):
    await browser.close()
    
# 如何启动?
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    browser, page = loop.run_until_complete(create_page())
    tasks = [asyncio.ensure_future(main(page=page))]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.run_until_complete(close_page(browser=browser))
  1. 以上是一个脚本开发的举例,爬虫相对会简单点,我们只要不被识别,渲染网页得到我们想要的html即可
# 修改上面的main方法即可,其他的同样适用
async def main(page):
    # 持久修改特征值,也就是navigator.webdriver
    # 此步参考来源 https://blog.csdn.net/weixin_41624982/article/details/89668879
    await page.evaluateOnNewDocument('() =>{ Object.defineProperties(navigator,'
                                     '{ webdriver:{ get: () => false } }) }')
    # 加载目标网站
   	# 设置目标网站,超时时间
    await page.goto('https://sellercenter.lazada.co.id/im/window',{'timeout': 1000*360})
    # xpath匹配式,顾名思义,等待关键节点的加载
    await page.waitForXPath("//input[@name='TPL_username']")	
    #获取文本
    html = await page.content()
    # 以下就可以用正则,xpath,bs4去解析我们想要的内容啦

你可能感兴趣的:(python3.x)