selenium和pywinauto实现贴吧自动发帖

说明:本文仅供学习参考;请勿用作其他用途

1.功能

  • 已经实现:实现贴吧自动发帖功能(包括标题,内容,上传图片),标题和内容加入了简单的随机字符串,每发一次会随机等待一段时间,关注人数少于50000的不发
  • 缺陷:自动登录需要关闭手机验证,且第一次验证码需要手动拖拽,有想法的同学可以买第三方来做验证码自动识别;发帖间隔不宜过快,否则每次发帖都会要求输入验证码

2.开始编码

以下部分直接上代码,有兴趣的朋友可以参考下...

# -*- coding: utf-8 -*-
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
import logging
import sys
import random
import uuid
import traceback
from pywinauto import Application
from pywinauto.keyboard import send_keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s', filemode='w',
                    filename="log.txt")
BROWSER_URL = r'D:\program files (x86)\360chrome\Chrome\Application\360chrome.exe'

from pywinauto.application import Application


class WinAuto:

    def __init__(self, class_name, title_re):
        # 连接到指定应用程序,此处为连接到指定窗口
        self.app = Application().connect(class_name=class_name, title_re=title_re)

    # 定位窗口方法
    def get_window(self, window_object, class_name="", title_re=""):
        return window_object.window(class_name=class_name, title_re=title_re)

    # 向编辑框输入指定信息
    def file_input(self, file_path):
        # 定位到标题名为“打开”对话框
        window = self.get_window(self.app, "#32770", "打开")
        # 定位到编辑框
        window = self.get_window(window, class_name="Edit")
        # 向编辑框中输入信息
        window.TypeKeys(file_path)

    # 点击【打开】按钮
    def open_button_click(self):
        # 定位到标题名为“打开”对话框
        window = self.get_window(self.app, "#32770", "打开")
        # 定位到【打开】按钮
        button = self.get_window(window, class_name="Button", title_re="打开")
        # 点击【打开】按钮
        button.click()


def get_titile():
    title_list = [
        "title1",
        "title2",
        "title3",
    ]
    t = random.choice(title_list)
    return t + str(random.choice(range(1000)))


def get_content():
    content = """
tests{uuid}eatet{uuid}aset""".format(uuid=str(random.choice(range(1000))))
    return content


def get_datas():
    with open('tieba.txt', 'r', encoding='utf-8', errors='ignore') as fp:
        schools = fp.readlines()
    return schools


def get_sleep_time(num):
    if num % 5 == 0:
        t = random.choice(range(120, 200))
    else:
        t = random.choice(range(35, 125))
    logging.info("sleep {}".format(t))
    return t


def find_ele(driver, element, timeout=10, trival=0.5, msg="", until_not=False):
    try:
        wait = WebDriverWait(driver, timeout, trival)
        if until_not:
            element = wait.until_not(element, message=msg)
        else:
            element = wait.until(element, message=msg)
    except TimeoutException:
        logging.error("{} not found".format(element.locator[1]))
        raise
    return element


def start_chrome():
    chrome_options = Options()
    chrome_options.binary_location = BROWSER_URL
    # chrome_options.add_argument("–incognito")
    driver = webdriver.Chrome(options=chrome_options)
    if login_tieba(driver):
        schools = get_datas()
        num = 0
        for name in schools:
            title = get_titile()
            content = get_content()
            url = u"https://tieba.baidu.com/f?ie=utf-8&kw=%s&fr=search" % name
            logging.info("start request {}, url:{}".format(name, url))
            try:
                driver.get(url)
                fans = find_ele(driver, EC.presence_of_element_located((By.CLASS_NAME, "card_menNum")), 20).text
                logging.info("fans is :{}".format(fans))
                fans = fans.replace(',', "")
                if int(fans) < 50000:
                    logging.info("fans lower 50000")
                    continue
                find_ele(driver, EC.presence_of_element_located((By.XPATH, "/html/body/ul/li[2]/a")), 20).click()
                sleep(1)
                find_ele(driver, EC.presence_of_element_located(
                    (By.XPATH, '//*[@id="tb_rich_poster"]/div[3]/div[1]/div[2]/input')), 20).send_keys(title)
                # driver.quit()
                sleep(1)
                find_ele(driver, EC.presence_of_element_located((By.ID, 'ueditor_replace')), 20).send_keys(content)
                sleep(1)
                find_ele(driver, EC.presence_of_element_located((By.CLASS_NAME, "edui-btn-image")), 20).click()
                sleep(1)
                find_ele(driver, EC.presence_of_element_located((By.CLASS_NAME, "pic_upload_container")), 20).click()
                sleep(1)
                find_ele(driver, EC.presence_of_element_located((By.CLASS_NAME, "next_step")), 20).click()
                sleep(1)
                # 定位打开窗口
                window = WinAuto("#32770", "打开")
                sleep(1)
                if num % 2 == 0:
                    # window.file_input(r'"F:\py_home\selenium_auto\2.jpg" "F:\py_home\selenium_auto\a.jpg"')
                    window.file_input(r"F:\py_home\selenium_auto\2.jpg")
                else:
                    # window.file_input(r'"F:\py_home\selenium_auto\3.jpg" "F:\py_home\selenium_auto\a.jpg"')
                    window.file_input(r"F:\py_home\selenium_auto\3.jpg")
                sleep(1)
                window.open_button_click()
                sleep(8)
                find_ele(driver, EC.presence_of_element_located((By.LINK_TEXT, "插入图片")), 20).click()
                sleep(1)
                find_ele(driver, EC.presence_of_element_located(
                    (By.XPATH, '//*[@id="tb_rich_poster"]/div[3]/div[5]/div/button[1]')), 20).click()
            except TimeoutException:
                logging.error("find element in tieba {} failed".format(name))
                continue
            except Exception as e:
                logging.error("post article failed,: {}".format(e))
                traceback.print_exc()
                continue
            num += 1
            t = get_sleep_time(num)
            sleep(t)
    driver.quit()


def login_tieba(driver):
    tieba_url = 'https://tieba.baidu.com/'
    driver.get(tieba_url)
    find_ele(driver, EC.presence_of_element_located((By.XPATH, '//*[@id="com_userbar"]/ul/li[4]/div/a')), 20).click()
    sleep(2)
    try:
        find_ele(driver, EC.presence_of_element_located((By.XPATH, '//*[@id="TANGRAM__PSP_11__footerULoginBtn"]')), 20).click()
        find_ele(driver, EC.presence_of_element_located((By.XPATH, '//*[@id="TANGRAM__PSP_11__userName"]')), 20).send_keys('问道哈时代')
        find_ele(driver, EC.presence_of_element_located((By.XPATH, '//*[@id="TANGRAM__PSP_11__password"]')), 20).send_keys('zh.900726')
        find_ele(driver, EC.presence_of_element_located((By.XPATH, '//*[@id="TANGRAM__PSP_11__submitWrapper"]')), 6).click()
        find_ele(driver, EC.presence_of_element_located((By.XPATH, '//*[@id="TANGRAM__PSP_11__footerULoginBtn"]')),timeout=60,until_not=True)
        logging.info("login success")
    except Exception:
        logging.error("login failed")
        logging.error(traceback.format_exc())
        sys.exit(1)
    return True


if __name__ == '__main__':
    start_chrome()


你可能感兴趣的:(selenium和pywinauto实现贴吧自动发帖)