selenium sends QQ automatically and regularly (super simple, super detailed)

Automatic timing transmission through selenium

Look at the overall code more. In fact, it's not much or difficult. It's just that I have a lot of code comments (my habit).

Sorry, the content of the article may be a little too much. In fact, I spend more time writing blog than writing code!

Let me be long winded. First use the trumpet to experiment, the lesson of tears! (I'm too confident)

I Programming idea and process

Enter QQ space.

# Prevent printing useless logs
option = webdriver.ChromeOptions()
option.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
# Use Google browser or you can also use Edge and Firefox
driver = webdriver.Chrome(chrome_options=option)
# Driver = webdriver is not used here Chrome (), because it will print a lot of useless logs

#window maximizing
driver.maximize_window()
#Open QQ space website
driver.get("https://i.qq.com")

2. Switch frames.

The window here is an iframe framework. If we want to locate the elements inside, we must first switch from the main framework to the iframe framework here

driver.switch_to.frame("login_frame")  #When you enter the frame, you can directly switch between id and name attributes

3. Log in to QQ space.

First check whether the computer has logged in to QQ. If you log in, log in to QQ space directly; Otherwise, log in with account and password

If you choose an account and password to log in, don't forget to fill in your account and password in the code

After careful observation, you will find that if you log in to QQ on the computer, there will be another < a > tag, so you can judge whether you log in to QQ. If you log in, you can directly locate the a tag and click it to complete the automatic login; If not, locate the "account and password login" in turn, click -- > enter account in the "account box -- > enter password in the" password box -- > click the "login" option

try:
        #Determine whether a tag exists
        element=driver.find_element_by_xpath("//div[@class='qlogin_list']/a")
        #Or directly drive find_ element_ by_ xpath("//div[@class='qlogin_list']/a")
        '''
            If it exists a Tag, continue to execute the following code and log in automatically
            Otherwise NoSuchElementException Exception, handle the exception directly, and log in with account and password
            NoSuchElementException: The element cannot be located, that is, the element does not exist, resulting in an exception
        '''
        #Method 1: automatic login (only after QQ has been logged in on the computer)
        driver.find_element_by_xpath("//div[@class='qlogin_list']/a").click()
        # Or driver find_ element_ by_ class_ name("login"). click()
except NoSuchElementException:
        # Method 2: enter the account and password to log in
        # Select account and password to log in
        driver.find_element_by_id("switcher_plogin").click()
        # Enter your qq account in the account box
        driver.find_element_by_id("u").send_keys("Your account number")
        # Enter the password in the password box
        driver.find_element_by_id("p").send_keys("Your password") 
        # Click the login button
        driver.find_element_by_id("login_button").click()
finally:
        print("Login successful")
    	time.sleep(2)    #Make sure you're logged in

4. Click to enter the talk page.

ps: Here's a reminder. Try the trumpet first, otherwise you will understand. Since then, I have used the trumpet for demonstration

Here, the < a > tag has no id and class attributes and cannot be located based on them, but link can be used_ Text to locate the text, or use xpath to locate layer by layer according to the path. First locate the < div > or < ul > tag on its outer layer, then locate < li > and finally < a >. The reason why < li > cannot be located directly is that Li and ul are integrated. The ul level is higher than Li, so it must be located to ul first

#Click the talk tab to talk about it
driver.find_element_by_xpath("//div[@class='head-nav']/ul/li[5]/a").click()
#This can be a driver find_ element_ by_ link_ Text ("talk") click()
#This doesn't work, driver find_ element_ by_ xpath("//li[@class='menu_item_311']/a")

5. Write and talk

  • Switch frames first. You can see that the area for writing and talking is located in the iframe framework.
'''
        there iframe No, id and name Property, but with class attribute
        So use it here class location iframe,Switch frames after positioning
    '''
    frame1 = driver.find_element_by_css_selector("iframe.app_canvas_frame")
    #Switch frame
    driver.switch_to.frame(frame1)
    time.sleep(2)  #Switching frames takes some time
  • Locate and click the text box. We can think about it. When writing and talking, we first point to the content area and fill in the content when the cursor appears. The same is true here
    '''
        Before filling in the talk content, you need to position the mouse in the talk text box.
    '''
    #Positioning text box
    driver.find_element_by_xpath("//div[@class='textinput textarea c_tx3']").click()
    #You can also use driver find_ element_ by_ id("$1_substitutor_content"). click()
    time.sleep(2)
    #Fill in the content
    driver.find_element_by_id('$1_content_content').send_keys("hello everyone! This is a pass selenium Automatic timing transmission")

6. Regular release (slightly troublesome)

Timing here, not difficult, just troublesome. The whole article is a little too much. I can't say more. Just be concise.

    #Select scheduled Publishing
    driver.find_element_by_xpath("//*[@class='sync-timing evt_click']").click()
    driver.find_element_by_link_text("Set publishing time").click()

Note that the pop-up window is in the main frame, not in the previous iframe frame, so go back to the main frame first

When we select the drop-down box, we find that we have entered the new iframe framework again

    #Regular publishing needs to return to the main framework first
    driver.switch_to.default_content()
    time.sleep(1)
    #Then enter an iframe pop-up frame and select the time of regular release
    driver.switch_to.frame("popup_dialog_frame")  #With id attribute, switch directly
    time.sleep(1)

#Select the number of days to publish
driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='date']").click()
#Option of the day [1] the first option is the day
driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='date']/option[1]").click()
#Select the hours to publish
driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='hours']").click()
 #0~23 option[24] at 23:00, i.e. 23:00
driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='hours']/option[24]").click() 
#Select the minutes to publish
driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='minutes']").click()
#20 points 0-59 option[21], i.e. 20 points
driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='minutes']/option[21]").click() 

At this time, we should think of one thing. What if our fixed time has expired? My processing is to cancel the scheduled direct release when it expires

We can judge whether the timing has expired according to whether there is text content in the indicated position in the picture

    judge_time=0  #Judge whether the timing is carried out. 0 is to be timed, and non-0 is not
    '''
        If the timing does not expire, select OK; Otherwise, select Cancel timing.
        If the timing expires, there will be a text prompt at the specified location,
        Therefore, we only need to judge whether the text in this position is empty to judge whether it has expired.
    '''
    if driver.find_element_by_xpath("//div[@class='tips tips_nobbor tips_highlight tips_icon icon_hint']").text == '':
        #Not expired, click OK
        driver.find_element_by_xpath("//a[@class='mod_btn mod_btn_sub']").click()
    else:
        #Expired, click Cancel
        driver.find_element_by_xpath("//a[@class='mod_btn mod_btn_nor']").click()
        #No timing
        judge_time=1

7. Make a statement (with key points)

Don't forget! Before we enter the timed pop-up window, we are also in an iframe frame

Therefore, to return to the previous iframe framework, we must first return to the main framework and then enter iframe

    #Back to the main frame
    driver.switch_to.default_content()
    time.sleep(0.5)

    #The iframe here has no id and name attributes, so you need to locate the iframe first, and then switch after positioning
    frame = driver.find_element_by_css_selector("iframe.app_canvas_frame")
    driver.switch_to.frame(frame)
    time.sleep(1)

Here's the point!

    #Click in the blank, otherwise you will not be able to locate the post (save) option later
    driver.find_element_by_xpath("//div[@class='bor mod-tab author_display']").click()
    time.sleep(0.5)

Here's a reminder. If we don't expire on time, the text content here will change from "publish" to "save", and others will remain unchanged. So don't use link_ Textpositioned

    '''
        #Click the publish (save) option to publish. 
        Here, because the text content is downloaded at irregular times, the text content after timing becomes saved,
        So it's not used here link_text Positioning.
    '''
    driver.find_element_by_xpath("//a[@class='btn-post gb_bt  evt_click']/span[@class='txt']").click()

If it is successfully released regularly, there will be a pop-up prompt

    '''
        judge_time A value of 0 indicates that the timing is to be confirmed, and a pop-up window will pop up for final confirmation,
        If it is not 0, there will be no pop-up window and publish directly without considering other issues
        In fact, it doesn't matter if you don't confirm it, because it's already scheduled.
    '''
    if judge_time == 0:
        #Back to the main frame
        driver.switch_to.default_content()
        #The delay here should be longer than 3s
        time.sleep(4)
        #The pop-up window here is div style, so there is no need to enter the iframe framework and other operations.
        #Therefore, the simplest positioning method is directly adopted here_ text. . 
        driver.find_element_by_link_text("confirm").click()

    print("Published successfully")

II Complete code

import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

# Prevent printing useless logs
option = webdriver.ChromeOptions()
option.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
# Use Google browser or Edge, Firefox
driver = webdriver.Chrome(chrome_options=option)
# Driver = webdriver is not used here Chrome (), because it will print a lot of useless logs

#window maximizing
driver.maximize_window()
#Open QQ space website 
driver.get("https://i.qq.com")

#try is used here. If there is a problem in the process, execute finally directly and close the window after 3s
try:
    driver.switch_to.frame("login_frame")  #Enter frame frame
    try:
        #Determine whether a tag exists
        element=driver.find_element_by_xpath("//div[@class='qlogin_list']/a")
        #Or directly drive find_ element_ by_ xpath("//div[@class='qlogin_list']/a")
        '''
            If it exists a Tag, continue to execute the following code and log in automatically
            Otherwise NoSuchElementException Exception, handle the exception directly, and log in with account and password
            NoSuchElementException: The element cannot be located, that is, the element does not exist, resulting in an exception
        '''
        #Method 1: automatic login (only after QQ has been logged in on the computer)
        driver.find_element_by_xpath("//div[@class='qlogin_list']/a").click()
        # Or driver find_ element_ by_ class_ name("login"). click()
    except NoSuchElementException:
        # Method 2: enter the account and password to log in
        # Because the table is in the iframe, you need to enter the iframe
        #driver.switch_to.frame("login_frame")  # Find the frame entry
        # Select account and password to log in
        driver.find_element_by_id("switcher_plogin").click()
        # Enter your qq account in the account box
        driver.find_element_by_id("u").send_keys("Your account number")
        # Enter the password in the password box
        driver.find_element_by_id("p").send_keys("Your password") 
        # Click the login button
        driver.find_element_by_id("login_button").click()
    finally:
        print("Login successful")
    time.sleep(2)

    #After logging in, it is a new page, which is already the main frame. There is no need to switch back to the main frame

    #Click the talk tab to talk about it
    driver.find_element_by_xpath("//div[@class='head-nav']/ul/li[5]/a").click()
    #driver.find_element_by_link_text("talk") click()
    #driver.find_element_by_xpath("//li[@class='menu_item_311']/a") doesn't work
    time.sleep(1)

    '''
        there iframe No, id and name Property, but with class attribute
        So use it here class location iframe,Switch frames after positioning
    '''
    frame1 = driver.find_element_by_css_selector("iframe.app_canvas_frame")
    #Switch frame
    driver.switch_to.frame(frame1)
    time.sleep(2)

    '''
        Before filling in the talk content, you need to position the mouse in the talk text box.
    '''
    #Positioning text box
    #You can also use driver find_ element_ by_ id("$1_substitutor_content"). click()
    driver.find_element_by_xpath("//div[@class='textinput textarea c_tx3']").click()
    time.sleep(2)
    #Fill in the content
    driver.find_element_by_id('$1_content_content').send_keys("hello everyone! This is a pass selenium Automatic timing transmission")

    #Select scheduled Publishing
    driver.find_element_by_xpath("//*[@class='sync-timing evt_click']").click()
    driver.find_element_by_link_text("Set publishing time").click()

    #Regular publishing needs to return to the main framework first
    driver.switch_to.default_content()
    time.sleep(1)
    #Then enter an iframe pop-up frame and select the time of regular release
    driver.switch_to.frame("popup_dialog_frame")
    time.sleep(1)
    #Select the number of days to publish
    driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='date']").click()
    driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='date']/option[1]").click() # current day
    #Select the hours to publish
    driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='hours']").click()
    driver.find_element_by_xpath("//Div [@ class ='mod_cont '] / P [@ id ='datesel'] / select [@ id ='hours'] / option [24] "). Click() #23
    #Select the minutes to publish
    driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='minutes']").click()
    driver.find_element_by_xpath("//div[@class='mod_cont']/p[@id='dateSel']/select[@id='minutes']/option[21]").click() #20 points

    judge_time=0  #Judge whether the timing is carried out. 0 is to be timed, and non-0 is not

    '''
        If the timing does not expire, select OK; Otherwise, select Cancel timing.
        If the timing expires, there will be a text prompt at the specified location,
        Therefore, we only need to judge whether the text in this position is empty to judge whether it has expired.
    '''
    if driver.find_element_by_xpath("//div[@class='tips tips_nobbor tips_highlight tips_icon icon_hint']").text == '':
        #Not expired, click OK
        driver.find_element_by_xpath("//a[@class='mod_btn mod_btn_sub']").click()
    else:
        #Expired, click Cancel
        driver.find_element_by_xpath("//a[@class='mod_btn mod_btn_nor']").click()
        #No timing
        judge_time=1

    #Back to the main frame
    driver.switch_to.default_content()
    time.sleep(0.5)

    #The iframe here has no id and name attributes, so you need to locate the iframe first, and then switch after positioning
    frame = driver.find_element_by_css_selector("iframe.app_canvas_frame")
    driver.switch_to.frame(frame)
    time.sleep(1)

    #Click in the blank, otherwise you will not be able to locate the post (save) option later
    driver.find_element_by_xpath("//div[@class='bor mod-tab author_display']").click()
    time.sleep(0.5)

    '''
        #Click the publish (save) option to publish. 
        Here, because the text content is downloaded at irregular times, the text content after timing becomes saved,
        So it's not used here link_text Positioning.
    '''
    driver.find_element_by_xpath("//a[@class='btn-post gb_bt  evt_click']/span[@class='txt']").click()

    '''
        judge_time A value of 0 indicates that the timing is to be confirmed, and a pop-up window will pop up for final confirmation,
        If it is not 0, there will be no pop-up window and publish directly without considering other issues
        In fact, it doesn't matter if you don't confirm it, because it's already scheduled.
    '''
    if judge_time == 0:
        #Back to the main frame
        driver.switch_to.default_content()
        #The delay here should be longer than 3s
        time.sleep(4)
        #The pop-up window here is div style, so there is no need to enter the iframe framework and other operations.
        #Therefore, the simplest positioning method is directly adopted here_ text. . 
        driver.find_element_by_link_text("confirm").click()

    print("Published successfully")
finally:                           #If there is a problem, close the window after 3s and exit QQ space
    #After 3s, close QQ space
    time.sleep(3)
    driver.quit()

III Summary and suggestions

In fact, there are many defects in the code. You can improve it

For example: sleep(),You shouldn't have used this, sleep Is precisely timed, that is to say
 If someone nets faster, he can sleep The time can be shorter; If the Internet is slow, it will take a little longer.
You can take a look at the display wait and implicit wait to try to change sleep. 

Selenium seems to me to be very simple. I just learned a little and just played, so I don't need to delve into the code of selenium why I did this.

  1. If you use sleep, you must consider your own network factors (i.e. insufficient delay) and whether the failure is caused by the network.
  2. I suggest you think more about using xpath. When you fail to locate with id, class, etc., you might as well try xpath. Maybe you will be surprised.

If there are questions about the content of the article, you can leave a message. If there are questions, you can also leave a message. I'll try my best to answer them.

Keywords: Python Selenium

Added by miked2 on Wed, 02 Feb 2022 23:52:12 +0200