Selenium 模拟微博登录


启用 ChromeDriver

def start_requests(self):
    """使用 selenium 获取 cookie"""
    # 获得 Options(操作)对象
    chrome_option = Options()

    # 添加到实例私有属性 self._arguments(论据)(list), 作为后续 webdriver 设置启动选项
    chrome_option.add_argument('--disable-extensions')  # 禁用扩展

    # 添加到实例私有属性 self._experimental_options(实验选择)(dict), 第一个参数为 key, 第二个参数为 value进行赋值
    # 也是作为后续 webdriver 启动设置选项
    chrome_option.add_experimental_option('debuggerAddress', '127.0.0.1:9222')  # 调试设置

    # 获取当前目录相对路径 string
    item_dir = os.path.dirname(os.path.abspath(__file__))

    # 打开 webdriver 启用配置
    with open(item_dir + r'/setting.conf') as f:
        exe_key = f.read()
    with open(item_dir + r'/executable_path.conf') as f:
        exe_path = json.loads(f.read())['chrome'][exe_key]

    # 传入可执行文件绝对路径, 此前 options 实例, 生成 browser 实例
    browser = webdriver.Chrome(executable_path=exe_path[0], chrome_options=chrome_option)

    # 调用实例 get 进入对应 web 页面
    browser.get(self.start_urls[0])

    # 放大 browser window
    try:
        browser.maximize_window()
    except:
        pass

模拟登录

# 避免输入框存在未知字符
browser.find_element_by_css_selector('input[id="loginname"]').send_keys(Keys.CONTROL + 'a')

# 定位到账号输入框, 输入账号
browser.find_element_by_css_selector('input[id="loginname"]').send_keys(WEIBO_CONFIG['account'])

# 避免输入框存在未知字符
browser.find_element_by_css_selector('input[type="password"]').send_keys(Keys.CONTROL + 'a')

# 定位到密码输入框, 输入密码
browser.find_element_by_css_selector('input[type="password"]').send_keys(WEIBO_CONFIG['password'])

# 定位到登录按钮, 触发点击事件
browser.find_element_by_css_selector('div[node-type="normal_form"] a[node-type="submitBtn"]').click()

验证码识别

针对动态验证码,处理验证码识别

截图当前验证码
# 给定循环条件
login_status = False
while not login_status:
    try:
        # 避免 web 页面响应时间过慢
        time.sleep(10)

        # 定位登录成功后 web 页面中的特定元素
        browser.find_element_by_css_selector('em[class="W_ficon ficon_mail S_ficon"]')

        # 已找到, 改变条件变量
        login_status = True

        # 跳出循环
        break

    # 未找到登录成功页面指定元素
    except:
        pass

    try:
        # 设置验证码图片, 保存相对路径
        captcha_code = BASE_DIR + r'\image\captcha_code.png'

        # 设置样本图片, 相对路径
        check_image = BASE_DIR + r'\image\check_image.png'

        # 寻找是否弹出验证码图片
        captcha_element = browser.find_element_by_css_selector('img[node-type="verifycode_image"]')

        # 获取元素属性 src
        captcha_url = captcha_element.get_attribute('src')

        # 判断是否包含 http / https (判断是否为 url)
        if 'http' in captcha_url or 'https' in captcha_url:

            # 引入第三方库, pyautogui(主要使用其截图功能)
            import pyautogui

            # 传入定位图片路径(string), 若定位成功可获取实例对象属性;
            # Box(left=1111, top=111, width=33, height=33), 可以下标索引/关键字取出
            point_coords = pyautogui.locateOnScreen(check_image)

            try:
                # 取出 x, y, width, height
                point_coord = [point_coords.left, point_coords.top, point_coords.width, point_coords.height]

            except KeyError as e:
                print('not found : {} . error:{}'.format(check_image, e))

            try:
                # 验证码修正左侧,顶部,宽度和高度 px
                correct = [120, -90, 30, 0]

                # 调用 zip 函数, 列表推导式方式, 对位相加数组中的元素, 获得修正后的坐标
                point_coord = tuple([px + p for px, p in zip(correct, point_coord)])

                # 调用 screenshot 入口, 传入图片保存路径, region=坐标
                pyautogui.screenshot(captcha_code, region=point_coord)
                print('captcha code image screenshot success!!!!!')

            except Exception as e:
                print(str(e))
调用第三方服务,识别验证码
# 调用 exists 函数, 传入路径, 判断验证码图片是否存在
if os.path.exists(captcha_code):

    # 实例化自定义工具类
    DC = DataConvert()

    # 取出保存验证码, 字节二进制数据
    image_data = open(captcha_code, 'rb').read()

    # 调用工具实例 -> 英文数字验证码识别方法, 传入二进制数据, 取出 pic_str key 的 value
    captcha_result = DC.check_english_captcha(image_data)['pic_str']
    print('receive code : <{}>'.format(captcha_result))

    # 定位到验证码输入框(因为是JS动态加载的, 不点击不会改变), 触发点击事件
    browser.find_element_by_css_selector('input[name="verifycode"]').click()
    print('----click input----')

    # 定位到验证码输入框, 输入验证码
    browser.find_element_by_css_selector('input[class="W_input W_input_focus"]'
                                         ).send_keys(captcha_result)
    print('-----input captcha code success------')

    # 点击登录按钮
    browser.find_element_by_css_selector(
        'div[node-type="normal_form"] a[class="W_btn_a btn_32px "]').click()
    print('----click login button-----')

    # 调用系统处理模块, 删除文件函数, 删除验证码图片
    os.remove(captcha_code)
获取cookie
    except:
        pass

# 循环执行以下代码
for i in range(3):
    # 调用 browser 实例中, 执行 JavaScript 代码方法, 以下参数为 JavaScript 代码(执行鼠标下滑操作)
    browser.execute_script('window.scrollTo(0, document.body.scrollHeight); var lenOfPage=document.body.scrollHeight; return lenOfPage;')
    time.sleep(3)

# 获取 cookies
cookies = browser.get_cookies()

# 列表推导式获取 cookie-dict, 保存对应 cookie, 调用工具类 dict 合并方法, 合并 dict
cookie = DataConvert.merge_dicts([{cookie['name']: cookie['value']} for cookie in cookies])

# 存储 cookie
pickle.dump(cookie, open(BASE_DIR + '/cookie/weibo.cookie', 'wb'))

for url in self.start_urls:
    yield scrapy.Request(url=url, cookies=cookie, dont_filter=True)

Author: Ming Hui
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Ming Hui !