Quel scrapy est encore utilisé! L'utilisation de ce framework est rapide et léger, il s'avère que les robots d'exploration sont si simples

Auparavant, nous écrivions des robots d'exploration, et le framework le plus utilisé était scrapy. Aujourd'hui, nous utilisons le nouveau framework de robot d'exploration feapder pour développer des robots d'exploration et voir de quel type d'expérience il s'agit.

Site Web cible: aHR0cHM6Ly93d3cubGFnb3UuY29tLw ==
Conditions requises: Collectez les listes de tâches et les détails des tâches, et les détails doivent être mis à jour tous les 7 jours.
À titre de démonstration, les éléments suivants ne recherchent que les messages liés aux robots d'exploration

1. Recherche

1.1 Page de liste

Tout d'abord, nous devons voir si la page est rendue dynamiquement et si l'interface est anti-escalade.

Pour voir s'il s'agit d'un rendu dynamique, vous pouvez cliquer avec le bouton droit de la souris pour afficher le code source de la page Web, puis rechercher l'existence du code source du contenu sur la page Web. Par exemple, si la première technologie Zhiyi de la liste de recherche correspond 0, il est initialement considéré comme un rendu dynamique

Ou vous pouvez utiliser la commande feapder pour télécharger le code source de la page Web et l'afficher.

La page ouverte est en cours de chargement

L'appel de la commande response.open () produira un fichier temp.html dans le répertoire de travail. Le contenu est le code source renvoyé par la requête en cours. Nous cliquons pour l'afficher. Il s'agit d'une section de js avec vérification de sécurité. Par conséquent, on peut en déduire que le site Web a un système anti-escalade et un avertissement précoce de la mise à niveau de difficulté

Feapder prend également en charge l'utilisation de la demande de commande curl, la manière est la suivante:

Appuyez sur F12 ou faites un clic droit pour vérifier, ouvrez la fenêtre de débogage, actualisez la page, cliquez sur la demande de la page actuelle, copiez-la en tant que curl, revenez à la fenêtre de ligne de commande, entrez dans le shell feapder - et collez le contenu qui vient d'être copié

 


On constate que le transport des en-têtes et des cookies n'est pas bon, peut-être que certains paramètres ne peuvent être utilisés qu'une seule fois.

Conclusion de la recherche: anti-escalade sur la page liste, rendu dynamique de la page

ps: Le dieu normal continuera à enquêter, quelle est l'interface de la liste, comment casser l'anti-crawl, mais parce que je suis un novice, je ne m'inquiéterai pas à ce sujet.

1.2 Page de détails

Semblable à l'enquête sur les pages de liste, la conclusion est qu'il existe un anti-crawl, mais la page n'est pas rendue dynamiquement

2. Créez le projet

Ouvrez l'outil de ligne de commande et entrez:

> feapder create -p lagou-spider                                                                                   

lagou-spider 项目生成成功

Le projet généré est le suivant:

J'utilise pycharm, clique d'abord avec le bouton droit de la souris et ajoute cet élément à l'espace de travail.
(Cliquez avec le bouton droit sur le nom du projet, Marquer le répertoire comme -> Racine des sources)

3. Rédigez un robot d'exploration de page de liste

3.1 Créer un robot d'exploration

> cd lagou-spider/spiders 
> feapder create -s list_spider 

ListSpider 生成成功

Le code généré est le suivant:

import feapder


class ListSpider(feapder.AirSpider):
    def start_requests(self):
        yield feapder.Request("https://www.baidu.com")

    def parse(self, request, response):
        print(response)


if __name__ == "__main__":
    ListSpider().start()

Ceci est un exemple de demande de Baidu, qui peut être exécuté directement

3.2 Reptiles photo

Tâches d'émission:

def start_requests(self):
    yield feapder.Request("https://www.lagou.com/jobs/list_%E7%88%AC%E8%99%AB?labelWords=&fromSearch=true&suginput=", render=True)

Notez que nous avons porté le paramètre de rendu dans la demande pour indiquer s'il faut utiliser le navigateur pour effectuer le rendu, car cette page de liste est rendue dynamiquement, et il y a un anti-crawl, je suis plutôt confus, j'ai donc utilisé le mode de rendu pour éviter la perte de cheveux

Ecrire des fonctions analytiques

Observez la structure de la page et écrivez la fonction analytique suivante

def parse(self, request, response):
    job_list = response.xpath("//li[contains(@class, 'con_list_item')]")
    for job in job_list:
        job_name = job.xpath("./@data-positionname").extract_first()
        company = job.xpath("./@data-company").extract_first()
        salary = job.xpath("./@data-salary").extract_first()
        job_url = job.xpath(".//a[@class='position_link']/@href").extract_first()

        print(job_name, company, salary, job_url)

Nous avons analysé le nom du poste, la société, le salaire et l'adresse détaillée du poste. La logique normale devrait envoyer l'adresse détaillée en tant que tâche pour obtenir les détails.

def parse(self, request, response):
    job_list = response.xpath("//li[contains(@class, 'con_list_item')]")
    for job in job_list:
        job_name = job.xpath("./@data-positionname").extract_first()
        company = job.xpath("./@data-company").extract_first()
        salary = job.xpath("./@data-salary").extract_first()
        job_url = job.xpath(".//a[@class='position_link']/@href").extract_first()

        print(job_name, company, salary, job_url)

        yield feapder.Request(
            job_url, callback=self.parse_detail, cookies=response.cookies.get_dict()
        )  # 携带列表页返回的cookie,回调函数指向详情解析函数

def parse_detail(self, request, response):
    print(response.text)
    # TODO 解析详情

Mais la condition est que les détails soient mis à jour tous les 7 jours, et la liste n'indique pas qu'elle doit être mise à jour. Par conséquent, afin d'optimiser, écrivez un robot distinct pour les détails. Ce robot est uniquement responsable des tâches de les données et les détails de production de la liste.

Beaucoup de gens apprennent le python et ne savent pas par où commencer.
Beaucoup de gens apprennent python et après avoir maîtrisé la grammaire de base, ils ne savent pas où trouver des cas pour commencer.
De nombreuses personnes qui ont fait des études de cas ne savent pas comment acquérir des connaissances plus avancées.
Donc pour ces trois types de personnes, je vais vous fournir une bonne plateforme d'apprentissage, gratuite pour recevoir des tutoriels vidéo, des e-books et le code source du cours!
Groupe QQ: 705933274

3.3 Stockage des données

Créer une table

Fiche technique de la liste des emplois lagou_job_list

CREATE TABLE `lagou_job_list` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `job_name` varchar(255) DEFAULT NULL COMMENT '职位名称',
  `company` varchar(255) DEFAULT NULL COMMENT '公司',
  `salary` varchar(255) DEFAULT NULL COMMENT '薪资',
  `job_url` varchar(255) DEFAULT NULL COMMENT '职位地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Tableau des tâches détaillé lagu_job_detail_task

CREATE TABLE `lagou_job_detail_task` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `url` varchar(255) DEFAULT NULL,
  `state` int(11) DEFAULT '0' COMMENT '任务状态(0未做,1完成,2正在做,-1失败)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Méthode de stockage des données

Il existe de nombreuses façons de stocker des données dans la base de données, en important directement pymysql, puis en épissant des instructions sql dans la base de données, ou en utilisant MysqlDB fourni avec le framework. Cependant, Feapder a un moyen plus pratique d'entreposage, l'entreposage automatique

Le stockage automatique d' AirSpider n'est pas pris en charge, car il est relativement léger. Afin de conserver la fonctionnalité légère, l'auteur ne prend pas en charge le stockage automatique pour le moment. Mais le robot d'exploration distribué Spider est pris en charge, nous intégrerons directement la classe à la place que Spider peut

class ListSpider(feapder.AirSpider):

À

class ListSpider(feapder.Spider):

Générer un élément

L'élément correspond à la table un par un, et est lié au mécanisme de stockage de données, et peut être généré par la commande feapder.

Commencez par configurer les informations de connexion à la base de données, qui sont configurées dans le paramètre

Générer un élément:

> cd items 
> feapder create -i lagou_job_list 
> feapder create -i lagou_job_detail_task

Stockage de données

def parse(self, request, response):
    job_list = response.xpath("//li[contains(@class, 'con_list_item')]")
    for job in job_list:
        job_name = job.xpath("./@data-positionname").extract_first()
        company = job.xpath("./@data-company").extract_first()
        salary = job.xpath("./@data-salary").extract_first()
        job_url = job.xpath(".//a[@class='position_link']/@href").extract_first()

        # 列表数据
        list_item = lagou_job_list_item.LagouJobListItem()
        list_item.job_name = job_name
        list_item.company = company
        list_item.salary = salary
        list_item.job_url = job_url
        yield list_item  # 直接返回,框架实现批量入库

        # 详情任务
        detail_task_item = lagou_job_detail_task_item.LagouJobDetailTaskItem()
        detail_task_item.url = job_url
        yield detail_task_item  # 直接返回,框架实现批量入库

Les données sont renvoyées au framework sous forme d'élément de rendement, et le framework est automatiquement stocké par lots

3.4 Code général

import feapder
from items import *


class ListSpider(feapder.Spider):
    def start_requests(self):
        yield feapder.Request(
            "https://www.lagou.com/jobs/list_%E7%88%AC%E8%99%AB?labelWords=&fromSearch=true&suginput=",
            render=True,
        )

    def parse(self, request, response):
        job_list = response.xpath("//li[contains(@class, 'con_list_item')]")
        for job in job_list:
            job_name = job.xpath("./@data-positionname").extract_first()
            company = job.xpath("./@data-company").extract_first()
            salary = job.xpath("./@data-salary").extract_first()
            job_url = job.xpath(".//a[@class='position_link']/@href").extract_first()

            # 列表数据
            list_item = lagou_job_list_item.LagouJobListItem()
            list_item.job_name = job_name
            list_item.company = company
            list_item.salary = salary
            list_item.job_url = job_url
            yield list_item  # 直接返回,框架实现批量入库

            # 详情任务
            detail_task_item = lagou_job_detail_task_item.LagouJobDetailTaskItem()
            detail_task_item.url = job_url
            yield detail_task_item  # 直接返回,框架实现批量入库


if __name__ == "__main__":
    spider = ListSpider(redis_key="feapder:lagou_list")
    spider.start()

redis_key est l'emplacement où la file d'attente des tâches est stockée dans redis.

Exécutez directement et observez que les données ont été automatiquement stockées dans la base de données

4. Écrire les détails du robot d'exploration

Contrairement aux robots d'exploration de pages de liste, les données détaillées doivent être mises à jour tous les 7 jours.

Afin d'afficher les données de séries chronologiques, nous collectons des données tous les 7 jours. Les données doivent contenir des informations sur les lots et diviser les données selon la dimension 7 jours.

Avant de contacter le framework feapder, nous devons envisager de transférer les tâches de la table des tâches détaillée au robot d'exploration par lots, et également de maintenir l'état des tâches et les informations de lot mentionnées ci-dessus. Et afin de garantir l'actualité des données, il est nécessaire de surveiller la progression de la collecte, et l'écriture d'un robot d'exploration est très fastidieuse.

Alors, comment fait Feapder? Afin de gagner de la place, donnez directement le code complet:

import feapder
from items import *


class DetailSpider(feapder.BatchSpider):
    def start_requests(self, task):
        task_id, url = task
        yield feapder.Request(url, task_id=task_id, render=True)

    def parse(self, request, response):
        job_name = response.xpath('//div[@class="job-name"]/@title').extract_first().strip()
        detail = response.xpath('string(//div[@class="job-detail"])').extract_first().strip()

        item = lagou_job_detail_item.LagouJobDetailItem()
        item.title = job_name
        item.detail = detail
        item.batch_date = self.batch_date  # 获取批次信息,批次信息框架自己维护
        yield item  # 自动批量入库
        yield self.update_task_batch(request.task_id, 1)  # 更新任务状态


if __name__ == "__main__":
    spider = DetailSpider(
        redis_key="feapder:lagou_detail",  # redis中存放任务等信息的根key
        task_table="lagou_job_detail_task",  # mysql中的任务表
        task_keys=["id", "url"],  # 需要获取任务表里的字段名,可添加多个
        task_state="state",  # mysql中任务状态字段
        batch_record_table="lagou_detail_batch_record",  # mysql中的批次记录表
        batch_name="详情爬虫(周全)",  # 批次名字
        batch_interval=7,  # 批次周期 天为单位 若为小时 可写 1 / 24
    )

    # 下面两个启动函数 相当于 master、worker。需要分开运行
    # spider.start_monitor_task() # 下发及监控任务
    spider.start()  # 采集

Nous exécutons respectivement spider.start_monitor_task () et spider.start (), et une fois le robot terminé, observez la base de données

Tableau des tâches : lagu_job_detail_task

Toutes les tâches ont été achevées et le cadre dispose d'un mécanisme pour renvoyer les tâches après des tâches manquantes jusqu'à ce que toutes les tâches soient terminées

Fiche technique : lagu_job_detail:

Les données contiennent des informations de temps de lot, et nous pouvons diviser les données en fonction de cette heure. Le lot actuel est le 19 mars. Si le lot se produit dans les 7 jours, le prochain lot aura lieu le 26 mars.

Démarrez le robot d'exploration à plusieurs reprises pendant ce lot. S'il n'y a pas de nouvelle tâche, le robot ne récupérera pas
spider.start_monitor_task ()


spider.start ()

Table de lots : lagu_detail_batch_record

La table de lots est spécifiée dans les paramètres de démarrage et est générée automatiquement. La table de lots enregistre en détail l'état de capture de chaque lot, comme le nombre total de tâches, le montant effectué, le montant de l'échec, s'il a été terminé et d'autres informations.

5. Intégration

À l'heure actuelle, le robot d'exploration de liste et le robot d'exploration détaillé ont été écrits. L'entrée en cours d'exécution est distribuée dans deux fichiers, ce qui est compliqué à gérer. Feapder recommande de l'écrire dans main.py.


from feapder import ArgumentParser

from spiders import *


def crawl_list():
    """
    列表爬虫
    """
    spider = list_spider.ListSpider(redis_key="feapder:lagou_list")
    spider.start()


def crawl_detail(args):
    """
    详情爬虫
    @param args: 1 / 2 / init
    """
    spider = detail_spider.DetailSpider(
        redis_key="feapder:lagou_detail",  # redis中存放任务等信息的根key
        task_table="lagou_job_detail_task",  # mysql中的任务表
        task_keys=["id", "url"],  # 需要获取任务表里的字段名,可添加多个
        task_state="state",  # mysql中任务状态字段
        batch_record_table="lagou_detail_batch_record",  # mysql中的批次记录表
        batch_name="详情爬虫(周全)",  # 批次名字
        batch_interval=7,  # 批次周期 天为单位 若为小时 可写 1 / 24
    )

    if args == 1:
        spider.start_monitor_task()
    elif args == 2:
        spider.start()


if __name__ == "__main__":
    parser = ArgumentParser(description="xxx爬虫")

    parser.add_argument(
        "--crawl_list", action="store_true", help="列表爬虫", function=crawl_list
    )
    parser.add_argument(
        "--crawl_detail", type=int, nargs=1, help="详情爬虫(1|2)", function=crawl_detail
    )

    parser.start()

Affichez la commande de démarrage:

> python3 main.py --help                                 
usage: main.py [-h] [--crawl_list] [--crawl_detail CRAWL_DETAIL]

xxx爬虫

optional arguments:
  -h, --help            show this help message and exit
  --crawl_list          列表爬虫
  --crawl_detail CRAWL_DETAIL
                        详情爬虫(1|2)

Démarrez le robot d'exploration de liste:

 python3 main.py --crawl_list

Démarrez le maître du robot d'exploration détaillé

python3 main.py --crawl_detail 1 

Démarrez le robot d'exploration détaillé

python3 main.py --crawl_detail 2

Pour résumer

Cet article prend un site Web de recrutement comme exemple et présente l'ensemble du processus de collecte de données à l'aide de feapder. Ce qui implique l'utilisation de trois robots AirSpider, Spider, BatchSpider.

  • Le robot d'exploration AirSpider est relativement léger et a de faibles coûts d'apprentissage. Face à un petit volume de données, pas besoin de continuer l'exploration sans points d'arrêt et pas besoin de collecte distribuée, ce robot peut être utilisé.
  • Spider est un robot d'exploration distribué basé sur redis, adapté à la collecte massive de données et prend en charge des fonctions telles que l'exploration continue aux points d'arrêt, les alarmes du robot d'exploration et le stockage automatique des données.
  • BatchSpider est un robot d'exploration de lots distribué. Pour les données qui doivent être collectées périodiquement, ce robot a la priorité.

En plus de prendre en charge le rendu et le téléchargement du navigateur, feapder prend également en charge le pipeline, qui peut être personnalisé par les utilisateurs pour faciliter l'ancrage avec d'autres bases de données.

Des alarmes riches sont intégrées dans le cadre et nous serons avertis à temps en cas de problème avec le robot d'exploration pour garantir la rapidité des données.

  1. Calculer la vitesse d'exploration du robot d'exploration en temps réel, estimer le temps restant et prédire s'il expirera dans le cycle d'exploration spécifié
  2. Reptile coincé alarme
  3. Trop d'alarmes de tâches du robot d'exploration ont échoué, ce qui peut être causé par des modifications ou un blocage du modèle de site Web
  4. Télécharger la surveillance de l'état

Je souhaite toujours recommander le groupe d'apprentissage Python Q que j'ai créé moi - même : 705933274. Le groupe apprend entièrement Python. Si vous voulez apprendre ou apprenez Python, vous êtes invités à le rejoindre. Tout le monde est une équipe de développement de logiciels et partage de la marchandise sèche. de temps en temps (uniquement lié au développement de logiciels Python), y compris une copie des derniers matériaux avancés Python et un enseignement basé sur zéro compilé par moi-même en 2021. Bienvenue aux avancés et aux amis intéressés par Python à rejoindre!

Je suppose que tu aimes

Origine blog.csdn.net/pyjishu/article/details/115264716
conseillé
Classement