Comment obtenir des informations sur les articles via l'automatisation de l'interface utilisateur ?

Pour l'étude et la recherche, j'ai analysé les articles et les vidéos d'un certain compte, et j'ai essayé d'utiliser des méthodes automatisées pour voir si je pouvais obtenir les informations correspondantes.

Il existe plusieurs façons d'obtenir des articles d'un certain nombre :

La première consiste à rechercher le compte via le navigateur Sogou (cette méthode ne peut obtenir qu'un seul article par jour, ce qui est fondamentalement inutile.):

image

Si vous souhaitez apprendre les tests d'automatisation d'interface, je vous recommande ici une série de vidéos. Cette vidéo peut être considérée comme le didacticiel de test d'automatisation d'interface numéro un sur l'ensemble du réseau à la station B. Dans le même temps, le nombre de les utilisateurs ont atteint 1 000, et il y a des notes à collecter et à utiliser.Échanges techniques de divers maîtres : 798478386    

[Mise à jour] La collection la plus détaillée de tutoriels pratiques pour les tests automatisés des interfaces Python enseignés par la station B (la dernière version du combat réel)_哔哩哔哩_bilibili [Mise à jour] La collection la plus détaillée de tutoriels pratiques pour les tests automatisés de Python interfaces enseignées par la station B (combat réel) La dernière version) a un total de 200 vidéos, y compris : 1. [Interface Automation] La situation actuelle du marché des tests de logiciels et les normes de capacité des testeurs. , 2. [Interface Automation] Complètement compétent dans la bibliothèque Requests et la logique d'appel de méthode sous-jacente, 3. [Interface Automation] combat l'automatisation de l'interface et l'application d'expressions régulières et d'extracteurs JsonPath, etc. Pour des vidéos plus intéressantes, veuillez prêter attention à le compte UP. https://www.bilibili.com/video/BV17p4y1B77x/?spm_id_from=333.337&vd_source=488d25e59e6c5b111f7a1a1a16ecbe9a 

La deuxième méthode nécessite que vous enregistriez vous-même un compte d'abonnement, et il existe des restrictions sur le compte d'enregistrement :

1. Un e-mail ne peut s'appliquer qu'à un seul compte ;

2. Le même numéro de téléphone portable peut être lié à 5 comptes ;

3. Le nombre maximum de comptes personnels enregistrés avec la même carte d'identité est de 1 ;

4. Le nombre maximum de comptes enregistrés pour la même entreprise, ménage individuel industriel et commercial et autres matériels organisationnels est de 2 ;

5. Le même type de gouvernement et de média peut enregistrer et authentifier 50 comptes ;

6. Le nombre maximum de comptes enregistrés par la même entité étrangère est de 1.

Cela signifie qu'une personne ne peut enregistrer qu'un seul numéro et peut postuler pour un média ou un gouvernement avec des numéros 50. Pour la recherche et l'étude, un seul suffit.

Sans parler du processus d'inscription, après l'inscription et la connexion, cliquez sur "boîte de brouillon" ---> "écrire une nouvelle image et un nouveau texte" ---> cliquez sur le "lien hypertexte" en haut --> cliquez sur "sélectionner un autre compte" au niveau du compte -->Entrez le nom du compte qui a besoin d'obtenir des articles , cliquez sur Requête, vous pouvez voir à ce moment, tous les articles de ce compte seront obtenus :

image

Par exemple, si nous interrogeons "CCTV", les articles seront affichés dans l'ordre inverse selon la date de sortie, c'est la donnée que nous souhaitons obtenir. Notre fonctionnement automatisé sera simulé à cet endroit, et le reste est juste pour analyser l'interface :

Grâce à l'analyse de la demande, la demande d'obtention d'articles est :

https://mp.weixin.qq.com/cgi-bin/appmsg?action=list_ex&begin=35&count=5&fakeid=MTI0MDU3NDYwMQ==&type=9&query=&token=441171486&lang=zh_CN&f=json&ajax=1

image

Les données renvoyées par l'interface sont très complètes, et en gros toutes les données que vous souhaitez sont disponibles.

Ce que nous avons à faire:

1. Simulez automatiquement l'opération de l'utilisateur à l'action en cours, puis obtenez la connexion de la demande et analysez les données de la demande

2. Pour appeler directement cette interface pour obtenir des données, il est alors nécessaire de construire les paramètres de requête de cette interface, tels que l'identifiant de compte, le cookie, etc., la maintenance de la connexion, etc.

En comparant les deux méthodes, les deux ont des avantages correspondants. Pour l'automatisation, il vous suffit d'entrer le nom du compte après vous être connecté. Si vous appelez l'interface, différents comptes doivent conserver l'identifiant correspondant à l'avance, et il est plus facile d'être bloqué si vous appelez directement l'interface.

Les règles d'interdiction actuellement recherchées sont : chaque compte peut appeler l'interface 60 fois, et il sera banni pendant 1 heure lorsqu'il atteindra 60 fois. Il est inutile de changer d'IP, et cela peut continuer après 1 heure. Après avoir été banni plusieurs fois fois, le temps d'interdiction changera longtemps, jusqu'à 24 heures.

Certains disent, sans faire appel à l'interface, comment obtenir ces requêtes après automatisation ? Il existe deux façons :

  1. L'avantage d'installer mitmproxy par rapport à Charles et fiddler est qu'il peut être moqué par ligne de commande ou script

Mitmproxy peut non seulement capturer des paquets comme Charles, mais également effectuer un développement secondaire sur les données de la demande et entrer un degré élevé de personnalisation secondaire

Vous pouvez d'abord vérifier les documents pertinents sur le site officiel

Site officiel de mitmproxy : https://www.mitmproxy.org/
mitmproxy est très puissant, mais nous n'en avons pas besoin ici.

1. fil de sélénium 

Selenium Wire étend les liaisons Python de Selenium pour vous donner accès aux requêtes sous-jacentes effectuées par le navigateur. Vous écrivez du code de la même manière que vous écrivez Selenium, mais vous obtenez des API supplémentaires pour inspecter les demandes et les réponses et les modifier de manière dynamique. site officiel de mitmproxy :

https://github.com/wkeeling/selenium-wire

  • Python pur, API conviviale

  • Requêtes HTTP et HTTPS capturées

  • Intercepter les demandes et les réponses

  • Modifier les en-têtes, les paramètres, le contenu du corps à la volée

  • Capturer les messages WebSocket

  • Format HAR pris en charge

  • Prise en charge du serveur proxy

le fil de sélénium nous suffit. 

Après avoir su comment le faire, trions ce que nous devons préparer :

1. Installation de l'environnement

(1) environnement python (omis)

(2) téléchargement du pilote chromedriver :

http://chromedriver.storage.googleapis.com/index.html

(3) environnement mysql (omis)

2. Conception de la base de données

(1) weichat_news : table principale des actualités


CREATE TABLE `weichat_news` (
  `id` int NOT NULL AUTO_INCREMENT,
  `news_title` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文章名称',
  `news_cover` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文章封面图',
  `news_digest` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文章简要',
  `news_content_link` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文章内容连接',
  `account_id` int NOT NULL COMMENT '微信账号id',
  `weichat_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '微信账号名称',
  `news_create_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文章创建时间',
  `news_update_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文章更新时间',
  `update_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新时间',
  `insert_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文章插入时间',
  `is_video` int NOT NULL DEFAULT '0' COMMENT '是否执行video扫描',
  `have_video` int NOT NULL DEFAULT '0' COMMENT '是否含有视频',
  `is_content` int NOT NULL DEFAULT '0' COMMENT '是否获取内容',
  `is_push` int DEFAULT '0',
  `is_delete` int NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `title` (`news_title`) USING BTREE,
  KEY `link` (`news_content_link`) USING BTREE,
  KEY `idx_account_id` (`account_id`) USING BTREE,
  KEY `idx_1` (`have_video`,`is_delete`,`is_push`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='文章';

(2) weichat_account : la table des comptes à obtenir


CREATE TABLE `weichat_account` (
  `id` int NOT NULL AUTO_INCREMENT,
  `account` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号名称',
  `collection_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `is_delete` int DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='账号';

(3) run_account : table d'exécution du compte


CREATE TABLE `run_account` (
  `id` int NOT NULL AUTO_INCREMENT,
  `account_id` int NOT NULL COMMENT '账号id',
  `account` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号名称',
  `patch` int DEFAULT NULL,
  `run_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '执行时间',
  `is_delete` int DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='执行情况';

(4) news_video : tableau vidéo


CREATE TABLE `news_video` (
  `id` int NOT NULL AUTO_INCREMENT,
  `news_id` int NOT NULL COMMENT '文章id',
  `news_title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文章名称',
  `account_id` int NOT NULL COMMENT '公众id',
  `account` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号名称',
  `original_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原视频url',
  `cover` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `vid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `width` int NOT NULL COMMENT '视频宽度',
  `height` int NOT NULL COMMENT '视频高度',
  `video_quality_level` int NOT NULL COMMENT '视频级别',
  `video_quality_wording` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '清晰度',
  `qiniu_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '七牛转存url',
  `insert_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '插入时间',
  `is_delete` int DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='视频';

(5) news_content : tableau du contenu des actualités


CREATE TABLE `news_content` (
  `id` int NOT NULL AUTO_INCREMENT,
  `news_id` int NOT NULL,
  `news_title` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
  `insert_time` datetime DEFAULT NULL,
  `source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `is_delete` int DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `news_id` (`news_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='文章详情表';

(6) account_token : la table utilisée pour stocker l'arrière-plan du compte


CREATE TABLE `account_token` (
  `id` int NOT NULL AUTO_INCREMENT,
  `account` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号名称',
  `token` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录token',
  `update_time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'token更新时间',
  `freq_control_time` datetime DEFAULT NULL,
  `is_delete` int DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='采集所用账号token';

3. Conception des sous-modules

(1) Obtenez des informations de base sur l'article grâce à l'automatisation, telles que : image de couverture, lien d'accès à l'article, heure de l'article, etc.

(2) Ouvrir automatiquement le lien de l'article pour obtenir l'adresse de la vidéo contenue dans l'article. Il existe deux types de vidéos dans le détail de l'article :

A. Les vidéos ordinaires pour les détails de l'article peuvent généralement être directement analysées et téléchargées (les vidéos plus régulières dans les détails de l'article ci-dessous) :

image

B. La vidéo TX insérée dans les détails de l'article est au format m3u8. Vous devez télécharger le fichier ts pour synthétiser en mp4. S'il s'agit d'une vidéo TX, vous devez d'abord cliquer sur le bouton de lecture lors de l'automatisation, sinon vous ne pourrez pas pour obtenir l'adresse m3u8 :

Les deux méthodes de traitement vidéo sont différentes. Mon idée de traitement est : tous les articles sont connectés à l'automatisation, et le sélénium est utilisé pour afficher et attendre. Si vous trouvez un bouton vidéo, cliquez dessus, puis obtenez toutes les données de la demande pour une analyse ultérieure.

(3) Demandez directement l'adresse de l'article original et analysez le contenu via bs4 et lxml

  A. Supprimer le formatage indésirable

  B. Transférez l'image vers Qiniu (remplacez l'image dans le contenu d'origine après le transfert)

  C. Extrayez la balise vidéo d'origine (vous devez la remplacer une fois la vidéo téléchargée et transférée vers Qiniu et transcodée ultérieurement)

  D. Extrayez d'autres balises, telles que la source d'information, l'éditeur, le journaliste et d'autres champs

(4) Le compte étant banni, vous pouvez envisager de rejoindre un compte. Une fois le compte banni, déconnectez-vous du compte actuel, connectez-vous avec un nouveau compte et envoyez le code QR de connexion à DingTalk pour qu'il soit scanné.

  A. Pendant l'automatisation, le compte est bloqué et il n'y a pas de données lors de la requête d'articles, et l'interface revient avec une invite "freq control"

     B. Lorsque le compte est banni, insérez un enregistrement dans le tableau et mettez à jour l'heure d'interdiction. Lors de la récupération du compte, il est déterminé que l'heure d'interdiction est supérieure à 1 heure.

  C. En fait, le compte utilisé dépend de la personne qui numérise avec le téléphone mobile. Le navigateur dispose d'un cache de connexion. Avant que le compte ne soit bloqué, nous avons utilisé le cache du navigateur. Ainsi, lorsqu'il est automatisé, nous pas besoin de scanner le code QR à chaque fois. Oui, j'en parlerai plus tard.

  D. Lorsque vous devez vous connecter, envoyez la capture d'écran du code QR au groupe DingTalk. Ici, le temps d'attente de l'automatisation de la page peut être défini plus longtemps, par exemple 10 minutes.

  Classement des modules principaux :

image

 Partage de code partiel :

1 Obtenez la méthode principale de l'article :


def get_news_main():
    """
    获取文章
    :return:
    """

    # 查询需要的号
    wei_account = read_sql.deal_mysql("get_account.sql")
    max_patch = read_sql.deal_mysql("get_max_patch.sql")[0][0]

    if max_patch is None:
        max_patch = 1
    else:
        if len(wei_account) == 0:
            max_patch = max_patch + 1
            wei_account = read_sql.deal_mysql("get_account_all.sql")
    for i in wei_account:
        # now() > DATE_ADD(freq_control_time, INTERVAL 1 HOUR) // 这里获取没有被封禁的账号继续执行任务
        crawl_account_l = read_sql.deal_mysql("get_account_token.sql")
        if crawl_account_l:
            # 随机取一个用于爬取的账号
            crawl = random.randrange(len(crawl_account_l))
            # 所用来爬取账号的id
            crawl_account_id = crawl_account_l[crawl][0]
            # 所用来爬取账号的账号
            crawl_account = crawl_account_l[crawl][1]
            # # 所用来爬取账号的登录token
            crawl_token = crawl_account_l[crawl][2]
            # 待爬取的账号id
            account_id = i[0]
            # 待爬取的账号名称
            account_name = i[1]
            # 需要爬取的页数   //为1爬取两页,0开始
            page = 0
            # 自动化操作路径
            driver = news.get_news(crawl_token, account_name, page, crawl_account_id, crawl_account)
            try:
                time.sleep(1)
                # 获取文章数据
                news_data, freq = analyze_news.analyze_news(driver)
                # 数据插入数据库
                in_news.insert_news(account_id, account_name, news_data)
                # 获取了的账号存入run_account表
                in_run.insert_run_account(account_id, account_name, max_patch)
                # 如果账号被封禁则更新被禁时间,并退出当前账号
                if freq is True:
                    ua.update_account_token_freq(crawl_account_id)
                    # 被封禁的账号退出登录
                    driver = lg.login_out(driver)
            except Exception as e:
                print(e)
            finally:
                driver.quit()
        else:
            print('账号封禁中,暂不能执行任务!!')
            break

 (1) Méthode d'acquisition automatique


# -*- coding = utf-8 -*-
# ------------------------------
# @time: 2022/5/5 17:11
# @Author: drew_gg
# @File: get_wei_chat_news.py
# @Software: wei_chat_news
# ------------------------------

import os
import time
import random
import configparser
from seleniumwire import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from get_news import get_login_token as gt
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

pl = os.getcwd().split('wei_chat_news')
# chromedriver地址
driver_path = pl[0] + "wei_chat_news\\charomedriver\\chromedriver.exe"
# 主配置文件地址
config_path = pl[0] + "wei_chat_news\\common_config\\main_config.ini"
config = configparser.ConfigParser()
config.read(config_path)


def get_news(token, account_name, page_num, crawl_account_id, crawl_account):
    """
    获取新闻
    :param token: 登录后token
    :param account_name: 获取文章的账号
    :param page_num: 获取文章的页数
    :param crawl_account_id: 用于获取的账号id
    :param crawl_account: 用于获取的账号
    :return:
    """
    # ************************************************** #
    # 由于微信账号的限制,一个账号只能爬取60页的数据,封禁1小时!!
    # ************************************************** #

    # seleniumwire:浏览器请求分析插件
    # 浏览器缓存文件地址(谷歌浏览器)
    profile_directory = r'--user-data-dir=%s' % config.get('wei_chat', 'chromedriver_user_data')

    # *******配置自动化参数*********#
    options = webdriver.ChromeOptions()
    # 加载浏览器缓存
    options.add_argument(profile_directory)
    # 避免代理跳转错误
    options.add_argument('--ignore-certificate-errors-spki-list')
    options.add_argument('--ignore-ssl-errors')
    options.add_argument('--ignore-ssl-errors')
    # 不打开浏览器运行
    # options.add_argument("headless")
    # *******配置自动化参数*********#

    driver = webdriver.Chrome(executable_path=driver_path, options=options)
    # 最大化浏览器
    driver.maximize_window()
    wei_chat_url = config.get('wei_chat', 'wei_chat_url') + token
    # 微信账号地址
    driver.get(wei_chat_url)
    try:
        # 点击草稿箱  //如果找不到则认为是没有登录成功
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.XPATH, "//a[@title='草稿箱']"))).click()
    except Exception as e:
        # 调用扫码登录
        driver = gt.get_login_token(driver, wei_chat_url, crawl_account_id, crawl_account)
        print(e)
    try:
        # 点击草稿箱
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.XPATH, "//a[@title='草稿箱']"))).click()
        # 点击“新的创作”
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.CLASS_NAME, "weui-desktop-card__icon-add"))).click()
        # 点击“写新图文”
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.CLASS_NAME, "icon-svg-editor-appmsg"))).click()
        time.sleep(1)
        # 切换到新窗口
        driver.switch_to.window(driver.window_handles[1])
        # 点击“超链接”
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.ID, "js_editor_insertlink"))).click()
        # 点击“其他账号”
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.XPATH, "//button[text()='选择其他账号']"))).click()
        # 输入“账号名称”
        driver.find_element(By.XPATH, value="//input[contains(@placeholder, '微信号')]").send_keys(account_name)
        # 回车查询
        driver.find_element(By.XPATH, value="//input[contains(@placeholder, '微信号')]").send_keys(Keys.ENTER)
        # 点击确认账号
    # 吃掉本次异常,不影响后续任务
    except Exception as e:
        print(e)
    try:
        e_v = "//*[@class='inner_link_account_nickname'][text()='%s']" % account_name
        WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.XPATH, e_v))).click()
    except Exception as e:
        ee = e
        print('没有该账号:', account_name)
        return driver
    for i in range(page_num):
        time.sleep(random.randrange(1, 3))
        try:
            WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.XPATH, "//a[text()='下一页']"))).click()
            try:
                # 暂无数据 //可能该账号没有文章,也可能被封了,直接返回!
                no_data_e = "//div[@class='weui-desktop-media-tips weui-desktop-tips'][text()='暂无数据']"
                nde = WebDriverWait(driver, 5, 0.2).until(EC.presence_of_element_located((By.XPATH, no_data_e)))
                if nde:
                    return driver
            except Exception as e:
                ee = e
        except Exception as e:
            ee = e
            return driver
    return driver

Je suppose que tu aimes

Origine blog.csdn.net/m0_73409141/article/details/131773677
conseillé
Classement