【数据存储+多任务爬虫】

数据存储

peewee模块

第三方模块,也需要在cmd中安装。

from peewee import *

db = MySQLDatabase(
    "spider",
    host="127.0.0.1",
    port=3306,
    user='root',
    password='123456'
)

# 类==》表
class Person(Model):
    name = CharField(max_length=20)   # 类型/约束
    birthday = DateField(null=True)

    class Meta:
        database = db

db.create_tables([Person])

需要提前先创建一个库,如下:

52f7af64cf6e49eb8e95d8a802ddd5c3.png

 # 插入数据

p1 = Person(name='XX', birthday='2004-04-09')

p1.save()

import re

import requests
from peewee import *

db = MySQLDatabase(
    "spider",
    host="127.0.0.1",
    port=3306,
    user='root',
    password='123456'
)


class MaoYanData(Model):
    name = CharField(max_length=100)
    star = CharField(max_length=100)
    release_time = CharField(max_length=100)

    class Meta:
        database = db     # 把这张表创建到库里面

class MaoYanSpider:
    def __init__(self):
        self.url = 'https://www.maoyan.com/board/4?offset={}'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }

    def get_html(self, url):
        response = requests.get(url, headers=self.headers)
        return response.text

    def parse_html(self, html):
        '''
        提取数据的函数
        :param html: 在那个代码中寻找
        '''
        r_list = re.findall('<div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>', html, re.S)
        self.save(r_list)

    def save(self, data_list):
        for data in data_list:
            li = [
                data[0],
                data[1].split(':')[1].strip(),
                data[2].split(':')[1].strip(),
            ]
            data_object = MaoYanData(name=li[0], start=li[1], release_time=li[2])
            data_object.save()
            print(li)

    def run(self):
        for offset in range(0, 91, 10):
            url = self.url.format(offset)
            html = self.get_html(url=url)
            self.parse_html(html)
            print('-'*100)


db.create_tables([MaoYanData])   # 创建出这张表
MaoYanSpider().run()

多任务爬虫--进程

进程:程序在计算机中的一次执行过程

创建进程的两种方式:

方式一:

1.将需要进程执行的时间封装为函数

2.通过模块的Process类创建进程对象,关联函数

   Process() 参数:

  • target  绑定要执行的目标函数
  • args元组  给target函数位置传参

3.可以通过进程对象设置进程信息及属性

4.通过进程对象调用start启动进程

  • 新的进程是由原有进程的子进程,子进程复制父进程全部内存空间代码段,一个进程可以创建多个子进程。
  • 进程创建后,各个进程空间独立,互相没有影响。
  • 各个进程在执行上互不影响,也没有先后顺序关系。 

方式二:

1.继承Process类

2.重写__init__方法添加自己的属性,使用super()加载父类属性

3.重写run()方法,调用start自动执行run方法

生产者消费者模型:生产者专门生产数据,然后存在一个中间容器中。消费者在这个中间容器取出数据进行消费。通过生产者消费者模型,可以让代码达到高内聚低耦合的目标,让程序分工更加明确。

进程通信:进程间空间独立,资源部共享,此时在需要进程间数据传输就需要特定手段进行数据通信。常用进程间通信方法:消息队列,套接字等。

进程池:创建一定数量的进程来处理事件,事件处理完进程不退出而是继续处理其他事件,直到所有事件全都处理完毕统一销毁。增加进程的重复利用,降低资源消耗


一般爬取图片:

import os.path

import requests

'''获得所有英雄id'''
# https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2845381
'''用获取到的英雄id拼接{}获取不同英雄皮肤数据'''
# https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2845381

class LolImageSpider:
    def __init__(self):
        self.hero_list_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2845381'
        self.hero_info_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2845381'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }

    def get_hero_url(self, url):
        json_data = requests.get(url, headers=self.headers).json()
        for hero in json_data['hero']:
            # print(hero['heroId'])    # 在这里打印出所有数据后发现数字并不连贯,取出他们的id去进行拼接
            info_url = self.hero_info_url.format(hero['heroId'])
            response = requests.get(info_url, headers=self.headers).json()
            self.parse_data(response)

    def parse_data(self, response):
        skins_list = response['skins']
        for skins in skins_list:
            # print(skins)      # 拿到每个英雄的皮肤
            name = skins['name']
            main_img = skins['mainImg']
            if main_img:       # 判断是否有对应图片的皮肤
                self.parse_img_data(name, main_img)

    def parse_img_data(self, name, main_img):
        img = requests.get(main_img).content

        filename = 'lol'
        if not os.path.exists(filename):
            os.mkdir(filename)      # 如果没有名为lol的文件就创建文件
        with open(filename+f"/{name.replace('/', '')}.jpg", 'wb')as f:     # 以该皮肤命名这个图片(记得f"后面加一个/,在该文件夹下下载图片。其中将名字内有/的皮肤名字(k/DA)改成空格)
            f.write(img)
        print(name, main_img)


    def run(self):
        # 获取所有英雄的id,拼接成英雄图片的url请求地址
        self.get_hero_url(self.hero_list_url)

spider = LolImageSpider()
spider.run()

 但是会发现爬取速度很慢。

使用了进程的生产者消费者就会快很多:

import re
import requests

from multiprocessing import Process, Queue

headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }

class Producer(Process):
    def __init__(self, url_q, img_q):
        super().__init__()
        self.url_q = url_q
        self.img_q = img_q

    def run(self) -> None:
        while not self.url_q.empty():
            url = self.url_q.get()
            json_data = requests.get(url, headers=headers).json()
            skins_list = json_data['skins']
            for skins in skins_list:
                name = skins['name']
                main_img = skins['mainImg']
                if main_img:
                    self.img_q.put({"name": name, "main_img": main_img})


class Consumer(Process):
    def __init__(self, img_q):
        super().__init__()
        self.img_q = img_q

    def run(self) -> None:
        while True:
            img_obj = self.img_q.get()
            img = requests.get(img_obj.get("main_img")).content    # 拿到数据
            with open(f'lol/{img_obj.get("name")}.jpg', 'wb')as f:
                f.write(img)
            print(img_obj)


if __name__ == '__main__':
    # 存储不同英雄的url链接
    urlQueue = Queue()
    imgQueue = Queue()

    hero_list_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2845381'
    hero_info_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2845381'

    json_data = requests.get(hero_list_url, headers=headers).json()
    for hero in json_data['hero']:
        info_url = hero_info_url.format(hero['heroId'])
        urlQueue.put(info_url)        # 得到数据链接

    p_list = []
    # 启动三个生产者
    for i in range(3):
        p = Producer(urlQueue, imgQueue)
        p.start()        # 执行这个线程
        p_list.append(p)
    #
    for i in range(5):
        p = Consumer(imgQueue)
        p.start()

    for p in p_list:
        p.join()


进程池与线程池

创建一定数量的进程来处理事件,事件处理完进程不退出,继续处理其他事件,直到所有时间全都处理完毕统一销毁。会增加进程的重复利用,降低资源消耗。

开启进程池例子:

import time
# 开启一个进程池
from concurrent.futures import ProcessPoolExecutor

def task(url):
    time.sleep(3)
    print(url)

if __name__ == '__main__':
    pool = ProcessPoolExecutor(4)   # 固定开了4个进程
    url_list = ["www.xxx-{}.com".format(i) for i in range(12)]
    for url in url_list:
        pool.submit(task, url)   # 提交:函数名,参数

 开启线程池:

'''
进程:资源分配单位
线程:执行单位
'''

import time
# 开启一个线程池
from concurrent.futures import ThreadPoolExecutor

def task(url):
    time.sleep(3)
    print(url)

if __name__ == '__main__':
    pool = ThreadPoolExecutor(4)   # 固定开了4个进程
    url_list = ["www.xxx-{}.com".format(i) for i in range(12)]
    for url in url_list:
        pool.submit(task, url)   # 提交:函数名,参数

 线程的生产者消费者模型:

import re
import requests

from threading import Thread
import queue

headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }

class Producer(Thread):
    def __init__(self, url_q, img_q):
        super().__init__()
        self.url_q = url_q
        self.img_q = img_q

    def run(self) -> None:
        while not self.url_q.empty():
            url = self.url_q.get()
            json_data = requests.get(url, headers=headers).json()
            skins_list = json_data['skins']
            for skins in skins_list:
                name = skins['name']
                main_img = skins['mainImg']
                if main_img:
                    self.img_q.put({"name": name, "main_img": main_img})


class Consumer(Thread):
    def __init__(self, img_q):
        super().__init__()
        self.img_q = img_q

    def run(self) -> None:
        filename = 'lol'
        while True:
            img_obj = self.img_q.get()
            if not img_obj:
                break
            name = re.sub(r'[\/:*?<>|]', " ", img_obj.get("name"))
            img = requests.get(img_obj.get("main_img")).content    # 拿到数据

            with open(f'{filename}/{name}.jpg', 'wb')as f:
                f.write(img)
                print(img_obj)
                self.img_q.task_done()    # 提示完成(join的阻塞)


if __name__ == '__main__':
    # 存储不同英雄的url链接
    urlQueue = queue.Queue()
    imgQueue = queue.Queue()

    hero_list_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2845381'
    hero_info_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2845381'

    json_data = requests.get(hero_list_url, headers=headers).json()
    for hero in json_data['hero']:
        info_url = hero_info_url.format(hero['heroId'])
        urlQueue.put(info_url)        # 得到数据链接

    p_list = []
    # 启动三个生产者
    for i in range(3):
        p = Producer(urlQueue, imgQueue)
        p.start()        # 执行这个线程
        p_list.append(p)
    #
    for i in range(5):
        p = Consumer(imgQueue)
        p.start()

    for p in p_list:
        p.join() 

注意与进程区别——导包的不同和queue的调用。

 线程对于交互等的运行速度会比进程快

 进程对于算数等的运行速度会比线程快


Excel

安装第三方模块openpyxl

创建:

from openpyxl import workbook
wb = workbook.Workbook()
wb.save("1.xlsx")     # 在当前文件夹下创建一个excel表

获取内容:

from openpyxl import load_workbook

# 打开Excel
wb = load_workbook("1.xlsx")    # (相对路径)读取
# 选择要操作的sheet
print(wb.sheetnames)    # 获取所有表名 ['1表', '2表', '3表', '4表']
sheet = wb["1表"]     # 也可以:sheet = wb.worksheets[0]
print(sheet)      # <Worksheet "1表">
print(sheet.cell(1, 1).value)  # 拿到表中1行1列的数据  没获取到的话记得看一下编辑之后有没有保存哦

例子:

import re

import requests

from openpyxl import workbook

class MaoYanSpider:
    def __init__(self):
        self.url = 'https://www.maoyan.com/board/4?offset={}'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
        }
        self.wb = workbook.Workbook()   # 创建Excel
        self.sheet = self.wb.worksheets[0]   # 第一个表
        self.header = ["电影名", "主演", "上映时间"]   # 定义表头名字
        for i, item in enumerate(self.header, 1):     # 索引从1开始
            # print(i, item)     # 枚举(获取索引和名字)0 电影名   1 主演   2 上映时间(self.header后没有注明1之后打印出的结果)
            self.sheet.cell(1, i).value = item    # 把表头一个一个写进去(第一行第一个,第一行第二个...)
        self.wb.save("Top100.xlsx")

    def get_html(self, url):
        response = requests.get(url, headers=self.headers)
        return response.text

    def parse_html(self, html):
        '''
        提取数据的函数
        :param html: 在那个代码中寻找
        '''
        r_list = re.findall('<div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>', html, re.S)
        self.save(r_list)

    def save(self, data_list):
        for data in data_list:
            li = [
                data[0],
                data[1].split(':')[1].strip(),
                data[2].split(':')[1].strip(),
            ]
            print(li)
            # 获取Excel中最大行号
            max_row = self.sheet.max_row
            for i, item in enumerate(li, 1):
                cell = self.sheet.cell(max_row + 1, i)
                cell.value = item
            self.wb.save("Top100.xlsx")

    def run(self):
        for offset in range(0, 91, 10):
            url = self.url.format(offset)
            html = self.get_html(url=url)
            self.parse_html(html)
            print('-'*100)

MaoYanSpider().run()

结果:

88b728abdbb6442082353d72020544d2.png

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/385663.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于python深度学习的中文情感分析的系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

利用pandas库进行数据分析

一.这段代码的主要目的是读取IMDB电影数据集&#xff0c;并进行一些基本的数据分析 # codingutf-8 import pandas as pd import numpy as np from matplotlib import pyplot as plt# 定义CSV文件的路径 file_path ./IMDB-Movie-Data.csv# 使用pandas的read_csv函数读取CSV文件…

Codeforces Round 113 (Div. 2)E. Tetrahedron(dp、递推)

文章目录 题面链接题意题解代码总结 题面 链接 E. Tetrahedron 题意 从一个顶点出发走过路径长度为n回到出发点的方案总数 题解 考虑dp f [ i ] [ 0 ∣ 1 ∣ 2 ∣ 3 ] f[i][0|1|2|3] f[i][0∣1∣2∣3]:走了i步&#xff0c;现在在j点的方案总数 转移&#xff1a; f [ i ]…

力扣(LeetCode)数据结构练习题

今天来分享两道力扣&#xff08;LeetCode&#xff09;的题目来巩固上篇时间复杂度和空间复杂度的知识&#xff0c;也就是在题目上加上了空间复杂度和时间复杂度的限制。 目录 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c…

ubuntu下如何查看显卡及显卡驱动

ubuntu下如何查看显卡及显卡驱动 使用nvidia-smi 工具查看 查看显卡型号nvida-smi -L $ nvidia-smi -L GPU 0: NVIDIA GeForce RTX 3050 4GB Laptop GPU (UUID: GPU-4cf7b7cb-f103-bf56-2d59-304f8996e28c)当然直接使用nvida-smi 命令可以查看更多信息 $ nvidia-smi Mon Fe…

关于在分布式环境中RVN和使用场景的介绍3

简介 在《关于在分布式环境中RVN和使用场景的介绍2》和《关于在分布式环境中RVN和使用场景的介绍1》中我们介绍了RVN的概念和在一些具体用例中的使用。在本文中我们讨论一下在分布式环境中使用RVN需要注意的问题。 问题 我们在收到一条待处理的事件时&#xff0c;需要检查该…

2024.2.9

作业1 请使用递归实现n&#xff01; #include<stdio.h> #include<string.h> #include<stdlib.h>int fun(int m) {if(m0)return 1;else{return m*fun(m-1);} } int main(int argc, const char *argv[]) {int m;printf("please enter m:");scanf(&…

MySQL 升级脚本制作

当数据库更新字段后或添加一些基础信息&#xff0c;要对生产环境进行升级&#xff0c;之前都是手动编写sql&#xff0c;容易出错还容易缺失。 通过 Navcat 工具的数据库结构同步功能和数据同步功能完成数据库脚本的制作。 一、结构同步功能 1、选择 工具–结构同步&#xff1…

从零开始实现消息队列(一)

从零开始实现消息队列 .什么是消息队列需求分析核心概念模型 . 什么是消息队列 相信大家都了解过阻塞队列和生产者消费者模型,而阻塞队列最大的用途,就是用于实现生产者消费者模型,生产者消费者模型有以下好处: 解耦合 解释: 当主机A给主机B发消息时,A给B发送请求,B给A返回响应…

CTFshow web(php命令执行59-67)

web59 <?php /* # -*- coding: utf-8 -*- # Author: Lazzaro # Date: 2020-09-05 20:49:30 # Last Modified by: h1xa # Last Modified time: 2020-09-07 22:02:47 # email: h1xactfer.com # link: https://ctfer.com */ // 你们在炫技吗&#xff1f; if(isset($_POST…

2024.2.8

1. 现有文件test.c\test1.c\main.c,编写Makkefile Makefile&#xff1a; CCgcc EXEa.out OBJS$(patsubst %.c,%.o,$(wildcard *.c)) CFLAGS-c -oall:$(EXE)$(EXE):$(OBJS)$(CC) $^ -o $%.o:%.c$(CC) $(CFLAGS) $ $^.PHONY:cleanclean:rm $(OBJS) $(EXE) 2. C编程实现&#x…

基于Java (spring-boot)的音乐管理系统

一、项目介绍 播放器的前端&#xff1a; 1.首页&#xff1a;点击歌单中的音乐播放列表中的歌曲进行播放&#xff0c;播放时跳转播放界面&#xff0c;并显示歌手信息&#xff0c;同时会匹配歌词&#xff0c;把相应的歌词显示在歌词面板中。 2.暂停&#xff1a;当歌曲正在播放时…

5G NR 信道号计算

一、5G NR的频段 增加带宽是增加容量和传输速率最直接的方法&#xff0c;目前5G最大带宽将会达到400MHz&#xff0c;考虑到目前频率占用情况&#xff0c;5G将不得不使用高频进行通信。 3GPP协议定义了从Sub6G(FR1)到毫米波(FR2)的5G目标频谱。 其中FR1是5G的核心频段&#xff0…

155基于matlab 的形态学权重自适应图像去噪

基于matlab 的形态学权重自适应图像去噪&#xff1b;通过串并联的滤波降噪对比图&#xff0c;说明并联降噪的优越性。输出降噪前后图像和不同方法的降噪情况的信噪比。程序已调通&#xff0c;可直接运行。 155matlab 自适应图像降噪 串并联降噪 (xiaohongshu.com)

QT:实现图片选择器

一、效果图 二、用到的类 qApp&#xff1a;可以快速获取到项目目录位置。 QSettings &#xff1a;编写config文件&#xff0c;记录上次打开图片的位置&#xff0c;下次打开图片会从上次的位置查找图片。 QPixmap&#xff1a;用于图片的缩放&#xff0c;防止图片过小&#xff0…

Java+SpringBoot+Vue:高校科研管理的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

基于JAVA的贫困地区人口信息管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 人口信息管理模块2.2 精准扶贫管理模块2.3 特殊群体管理模块2.4 案件信息管理模块2.5 物资补助模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 人口表3.2.2 扶贫表3.2.3 特殊群体表3.2.4 案件表3.2.5 物资补助表 四…

fatal error: rtiostream_utils.h: No such file or directory, rtiostream.h

fatal error: rtiostream_utils.h: No such file or directory 我的设置&#xff1a;

Java+SpringBoot实习管理系统探秘

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

19 删除链表的倒数第 N 个结点

19. 删除链表的倒数第 N 个结点 中等 相关标签 相关企业 提示 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 这段代码使用了双指针的方法&#xff0c;其中一个指针先走 n 步&#xff0c;然后两个指针一起走&#xff0c;直到第一…