MiziSpider爬虫程序源码【单线程】【子类写法】【函数写法】

        最近一直在学目标检测,那里面python代码就达到了1000行左右,大量的数学逻辑,学着学着就想逃回农村,没有买卖就没有伤害。偶然间看到爬虫,花了一天时间学了一下,找了个网站,测试了一下,还是可以的,爬虫这个程序照着原理图做,还是还简单的。该爬虫只用于锻炼思维,交流学习。后续还可以继续完善。

1、通过本次爬虫程序,你将收获:

(1)、熟悉自定义函数调用,文件管理,子类写法,以及对网页html有一定程度的了解。

(2)、第三方库的熟悉,BeautifulSoup、Lxml、requests等等

(3)、练习手敲代码,活学活用

(4)、子类的写法,以及调用参数(重点)

2、改进方向

(1)多进程爬虫

(2)多线程爬虫

(3)分布式爬虫

3、原理及应用

一、原理

        爬虫(Web scraping)是指自动化地从网页中提取数据的过程。通过编写爬虫程序,您可以访问互联网上的各种网站,并从网页中抓取所需的数据,如文本、图像、链接等。通用爬虫的流程如下下所示。

以下是一般的爬虫实现步骤:

1. **确定目标:** 确定您要爬取的网站或特定页面。确定您要提取的数据类型和所需的数据量。

2. **分析网页结构:** 使用开发者工具或查看网页源代码,了解目标网站的网页结构、HTML标签及数据位置。

3. **选择合适的爬虫工具/:** 选择适合您的编程语言的爬虫工具或库。常见的选择包括Python的Scrapy、BeautifulSoup和Requests库等。

4. **编写爬虫代码:** 使用选择的爬虫工具或库编写代码,以访问目标网站、抓取数据和处理数据。这可能涉及到发送HTTP请求、解析HTML、提取所需数据等任务。

5. **处理数据:** 对爬取的数据进行清洗、处理和整理,使其符合您的需求,可能需要使用正则表达式、字符串操作或其他数据处理方法。

6. **存储和分析数据:** 将爬取的数据存储到数据库中或以其他格式保存,以便后续的数据分析和使用。

7. **设置爬虫策略:** 考虑目标网站的访问频率限制和爬虫伦理。设置适当的请求头、延迟时间和请求次数等,以遵守网站的服务条款并避免对网站造成过大的负担。

8. **运行和监控爬虫:** 运行您编写的爬虫代码,并实时监控其运行状态和输出。根据需要进行调整和修复代码中的问题。

请注意,当编写爬虫程序时,需要尊重网站的服务条款和法律法规,并确保所采集的数据是符合合法目的的。此外,了解基本的网络编程知识和HTML、CSS、XPath等方面的基础知识也会有所帮助。

二、应用

爬虫技术可以用于各种不同的目的和应用。以下是爬虫可以做的几个常见任务:

1. **数据采集和抓取:** 爬虫可以帮助您从互联网上收集大量的数据。您可以爬取新闻网站的文章、电子商务网站的产品信息、社交媒体平台的用户信息等。

2. **数据分析和挖掘:** 爬虫可以用来获取大量数据,并进行进一步的数据分析和挖掘。您可以通过分析爬取的数据,发现趋势、模式、关系等,并从中提取有价值的信息。

3. **搜索引擎索引:** 搜索引擎使用爬虫来抓取互联网上的网页,并建立索引以实现快速搜索。爬虫帮助搜索引擎发现新内容,更新现有内容,并确定网页的重要性和排名。

4. **价格比较和监测:** 通过爬取电子商务网站的产品信息,可以进行价格比较和监测。这对于在线购物和市场竞争分析非常有用。

5. **舆情监测:** 爬虫可以帮助您监测社交媒体、新闻网站和论坛等平台上关于特定话题的舆情和用户评论。

6. **内容聚合和推荐:** 爬虫可以从多个来源收集数据,并将其聚合为一个平台或应用程序。这样做可以提供更丰富的内容,并根据用户的兴趣进行个性化推荐。

7. **网站测试和监控:** 通过模拟用户行为和爬取网页内容,可以对网站进行测试和监控。这有助于发现网站的错误、漏洞和性能问题。

8. **自动化操作:** 爬虫可以用来执行一些常规和重复的网页操作,例如登录、提交表单、下载文件等。

需要注意的是,在进行任何爬虫活动时,应该遵守相关的法律法规和网站的服务条款。同时,尊重网站的机器人协议和数据隐私,并确保您的爬虫行为不会对目标网站造成过大的负担或损害。

4、步骤

(1)获取html页面。【get_html】

(2)解析页面,获得第一层目标。【parser_html】

(3)获取第二层目标总数。【get_pic_html】

(4)获取所有目标源文件。【get_pic_src】

(5)下载目标文件。【downloadpic】

注意:具体情况具体分析,一定要结合自己想要爬取的网页,做结构性分析,有些网页需要做多次结构分析,取决于你想一个py文件要下载多少文件,野心越大,需要做越多的分析,编程背后都是逻辑,学无止境呀呀呀呀呀。

5、环境准备

(1)电脑:什么电脑都可以,什么系统也行,不局限于windowns、macos、linux

(2)环境:简单点说,就是你固定生活的地方,可以搬动,但不建议,费心费力费时间

(3)版本:python 3开头的,太老的,也没有去关注

(4)本次使用的是mac,python 3.9、pycharm22.1

(5)目标网址:美女图片(纯粹是因为是图片数据库哦!!总得找一个爬哇)

6、代码实现

一、函数式写法

import os
import re
import time

import requests       
from requests import exceptions  
from bs4 import BeautifulSoup   
import numpy as np

url = "https://www.3gbizhi.com/meinv" 
img_path = "./picture"  # 定义一个文件路径来存储图片
ds_list = []            # 定义一个全局变量来记录照片的html地址
src_list = []           # 定义一个全局变量来记录照片的url地址
count = 0               # 定义一个全局变量来记录照片的数量
index_lst = []

headers = {
    'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (HTML, like Gecko)Chrome/80.0.3987.100 Safari/537.36",
    'Connection': 'Keep-Alive', 
    'Referer': "https://www.3gbizhi.com/meinv/xgmn/" 
}


def down_html_first(url):
    """ 获取第一阶段的html页面"""
    try:
        resp = requests.get(url, headers=headers)
        resp.raise_for_status()
        return resp.text
    except exceptions.Timeout as e:
        print(e)
    except exceptions.HTTPError as e:
        print(e)


def parse_html(html):
    """ 解析获取所有的妹子html  """
    soup = BeautifulSoup(html, "lxml")
    a_list = soup.find_all("a")  # find all named a tag in parsed data,and return a list
    href_list_f = []
    for a in a_list:
        url_ = a.get('href')
        if url_ is None:
            continue
        if url_.startswith('https') and url_.endswith('html'):
            href_list_f.append(url_)
    href_list_new = []
    for b in href_list_f:
        if re.findall("index", b, flags=0):
            index_lst.append(b)
            continue
        if re.findall("connect", b, flags=0):
            continue
        href_list_new.append(b)
    save(index_lst, "./index.txt")
    # href_list_new = [x for i, x in enumerate(href_list_new) if x not in href_list_new[:i]]
    href_list_new = list(set(href_list_new))  # drop duplicate
    print(f"steps two:wanted htmls have been parsing,the first class web's gal of {len(href_list_new)} in total!")
    return href_list_new


def save(lst, path):
    for i in lst:
        with open(f"{path}", "a+") as f:
            f.write(i + "\n")
    print(f"保存了{len(lst)}个目标!")


def get_pic_html_num(html):
    """ 获取妹子所有图片的html及数量 """
    count = 0  
    print(html)
    for url2 in html:
        addr = url2.rsplit(".", 1)[0]
        resp = requests.get(url2, headers)
        soup = BeautifulSoup(resp.text, "lxml")
        a_list = list(soup.find_all("a"))
        # global ds_list=[]
        for a in a_list:
            url_ = a.get('href')
            if url_ is None:
                continue
            if url_.startswith('https') and url_.endswith('html'):
                if url_.rsplit("_")[0] == addr:
                    ds_list.append(url_)
                    count = count + 1
    print(f"第三步:已经在正常获取获取妹子所有图片的html及数量为{count}")
    print(ds_list[:9])
    return ds_list


def get_pic_url(href_list):
    """ 获取所有妹子的图片url """
    for href_ in href_list:
        html_img = down_html_first(href_)
        soup = BeautifulSoup(html_img, "lxml")
        img_list = soup.find_all("img", attrs={"id": "contpic"})
        # print(img_list)
        for a in img_list:
            url_ = a.get('src')
            if url_ is None:
                continue
            if url_.startswith('https') and url_.endswith('.jpg'):
                src_list.append(url_)
    print(f"第四步:已经获取{len(src_list)}的图片原地址!!,请稍等,正在准备下载中")
    print(src_list[:2])
    return src_list


def download_pic(src_list):
    """ 下载妹子的图片 """
    if not os.path.exists(img_path):
        print(f'{img_path} does not exist')
        os.makedirs(f"{img_path}/")
        print(f'{img_path} has been created!!')
    type(src_list)
    for url1 in src_list:
        print(url1)
        img = requests.get(url1, headers=headers)
        t = time.time()
        now_time = lambda: int(round(t * 1000))
        print('downloading... ', url1)
        with open("./picture/{0}_{1}.jpg".format(count, now_time()), 'ab') as f:
            f.write(img.content)
        time.sleep(1)
        img.close()
        print('the pictures that you want to drop have download completely!')


if __name__ == '__main__':
    count = 0
    html = down_html_first(url)  
    print("第一步:已经正常获得第一层的网页!!!")
    time.sleep(np.random.randint(0, 2))
    # 解析html页面文档,返回一个html的列表
    href = parse_html(html)  
    destination = get_pic_html_num(href) 
    drs = get_pic_url(destination)
    print("第五步:已经正常所有目标的url,正在下载高清原图!!")
    save(drs, ".//source_yrl.txt")
    download_pic(drs)

二、子类写法

# Editor——>File and Code Template——>Python Script
# 姓名:亮
# 开发时间:2023/6/23 11:37
import os
import re
import time
import datetime

import requests   
from requests import exceptions  #
from bs4 import BeautifulSoup    # 导入网页解析库
import numpy as np


class MeiziSpider:
    def __init__(self, url, img_path):
        self.url = url
        self.img_path = img_path
        self.html_list = []
        self.src_list = []
        self.count = 0
        self.num = 0
        self.index_lst = []
        self.step = 0
        self.headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (HTML, like Gecko)Chrome/80.0.3987.100 Safari/537.36",
            'Connection': 'Keep-Alive',
            'Referer': "https://www.3gbizhi.com/meinv/xgmn/"
        }

    def get_html(self, url):
        """1.获取html页面"""
        try:
            resp = requests.get(url, headers=self.headers)
            resp.raise_for_status()
            return resp.text
        except exceptions.Timeout as e:
            print(e)
        except exceptions.HTTPError as e:
            print(e)

    def parse_html(self, html):
        """2.解析html页面,获取第一层目标"""
        soup = BeautifulSoup(html, "lxml")
        a_list = soup.find_all("a")
        href_list_f = []
        for a in a_list:
            url_ = a.get('href')
            if url_ is None:
                continue
            if url_.startswith('https') and url_.endswith('html'):
                href_list_f.append(url_)
        href_list_s = []
        for index in href_list_f:
            if re.findall("index", index, flags=0):
                self.index_lst.append(index)
                continue
            if re.findall("connect", index, flags=0):
                continue
            href_list_s.append(index)
        self.save(self.index_lst, "./index.txt")
        href_list_s = list(set(href_list_s))
        self.step += 1
        print(f"steps {self.step}/5: first-layer web pages have been parsed, get targets of {len(href_list_s)}.")
        return href_list_s

    def save(self, lst, path):
        for i in lst:
            with open(f"{path}", "a+") as f:
                f.write(i + "\n")
        print(f"Saved {len(lst)} targets!")

    def get_pic_html(self, html):
        """3.解析html页面,获取第二层目标"""
        for url2 in html:
            addr = url2.rsplit(".", 1)[0]
            resp = requests.get(url2, self.headers)
            soup = BeautifulSoup(resp.text, "lxml")
            a_list = list(soup.find_all("a"))
            for tag in a_list:
                url_ = tag.get('href')
                if url_ is None:
                    continue
                if url_.startswith('https') and url_.endswith('html'):
                    if url_.rsplit("_")[0] == addr:
                        self.html_list.append(url_)
                        self.count += 1
        self.step += 1
        print(f"Step {self.step}/5: Successfully obtained all the HTMLs and the number of pictures is {self.count}")
        print(self.html_list[:1])
        return self.html_list

    def get_pic_src(self, href_list):
        """4.解析html页面,获取所有目标的源地址"""
        for href_ in href_list:
            html_img = self.get_html(href_)
            soup = BeautifulSoup(html_img, "lxml")
            img_list = soup.find_all("img", attrs={"id": "contpic"})
            for a in img_list:
                url_ = a.get('src')
                if url_ is None:
                    continue
                if url_.startswith('https') and url_.endswith('.jpg'):
                    self.src_list.append(url_)
        self.step += 1
        print(f"Step {self.step}/5: Successfully obtained {len(self.src_list)} original image addresses! ")
        print(self.src_list[:1])
        return self.src_list

    def download_pic(self, src_list):
        """5.解析https地址,下载所有的目标"""
        if not os.path.exists(self.img_path):
            print(f'{self.img_path} does not exist')
            print(f'{self.img_path} is creating now,please wait for a second!')
            os.makedirs(f"{self.img_path}/")
            self.step += 1
            print(f'{self.img_path} has been created! Please wait while preparing to download.')
            print(f"Step {self.step}/5: Successfully obtained all the target URLs and downloading source images!")

        for url1 in src_list:
            img = requests.get(url1, headers=self.headers)
            self.num += 1
            t = time.time()
            now_time = lambda: int(round(t * 1000))
            print('downloading... ', url1)
            with open(f"{self.img_path}/{self.num}_{now_time()}.jpg", 'ab+') as f:
                f.write(img.content)
            time.sleep(1)
            img.close()
        print('The pictures you selected have been downloaded completely!')

    def start_spider(self):
        """开始启动爬虫程序"""
        start = time.time()
        html = self.get_html(self.url)
        self.step += 1
        print(f"Step {self.step}/5: Successfully obtained the first layer of web pages!")
        time.sleep(np.random.randint(0, 2))
        href = self.parse_html(html)
        destination = self.get_pic_html(href)
        pic_src = self.get_pic_src(destination)
        self.save(pic_src, ".//source_url.txt")
        self.download_pic(pic_src)
        end = time.time()
        total_time = end - start
        time_format = str(datetime.timedelta(seconds=total_time))
        print(f"The programmer named MeiziSpider running {time_format} seconds in total!")


if __name__ == '__main__':
    url = "https://www.3gbizhi.com/meinv"
    img_path = "./picture1"
    spider = MeiziSpider(url, img_path)
    spider.start_spider()

结果展示部分

三、比较

        函数写法,还是比较随意的,一个个写完就完行了,相互调用,比较简单,但看着不太清楚,层次不如子类写法,子类写法看着舒服,层级清晰,不用担心变量找不到,但是呢,要求也相对高一些,需要对子类调用的又一个整体清晰的认识,二者也是联系的,并不是孤立存在的。

四、缺点

(1)时间效率

        本次实现的代码,时间响应还是很慢的,一在于代码本身,没有做优化,使用多线程等技术二、在于多次使用嵌套循环。三、python语言本身的问题,四、跟电脑、网络带宽有影响。前两者属于主观因素,可以进行优化,第三者属于半客观半主管,最后是属于客观因素,没有钱,穷,设么都对。因此本代码只能适用普通娱乐,学习交流,不适合商用,

(2)空间效率

        跟时间效率相似,可以做空间回收机制,减少内存的使用。

五、申明

        本次代码,整理于网络资源,自己根据实际需求改写,功能简单,若重合,实属于巧合。

  • 29
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

松花蛋卷蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值