当前位置: 首页 > article >正文

简单爬虫的实现

 以下是一个简单爬虫代码的实现:

import requests
from bs4 import BeautifulSoup

# 生成一个包含多个网页 URL 的列表
# 这里我们构造了 50 个页面的 URL,假设网站有多页内容,页数从 1 到 50
urls = [f"https://www.cnblogs.com/#p{i}" for i in range(1, 51)]  # #p1, #p2, ..., #p50

# 生产者——负责下载网页内容
def craw(url):
    """
    通过 requests 库向指定的 URL 发送 GET 请求,并返回响应的网页内容(HTML)
    """
    r = requests.get(url)  # 发送 GET 请求
    return r.text  # 返回网页的 HTML 内容

# 消费者——解析网页内容,提取有用信息
def parse(html):
    """
    解析 HTML 内容,提取其中所有 class 为 'post-item-title' 的超链接(<a> 标签)
    """
    soup = BeautifulSoup(html, "html.parser")  # 使用 BeautifulSoup 解析网页的 HTML 内容
    # 使用 find_all 方法查找所有 class 名为 'post-item-title' 的 <a> 标签
    links = soup.find_all("a", class_="post-item-title")
    
    # 遍历所有找到的 <a> 标签,提取每个标签的 href 属性和标签文本
    # 将 href(链接地址)和 get_text(链接的文字)以元组的形式返回
    return [(link["href"], link.get_text()) for link in links]

# 主程序——执行爬虫任务
if __name__ == '__main__':
    # 只处理第 3 个网页的内容(urls[2] 对应第 3 页,即 #p3)
    # 首先调用 craw 函数下载网页内容,然后将下载的 HTML 内容传给 parse 函数解析
    for result in parse(craw(urls[2])):
        # 输出每一个链接及其文字内容
        print(result)

 此时我们可以将上述爬虫代码作为我们基础的模块,通过多线程爬取,将我们爬取到的信息保存到文件当中,以下是一个用例来实现我们的要求:

import threading
import time
import random
import queue
import blog_spider  # 导入自定义的爬虫模块

# 生产者线程:负责从 url_queue 中取出 URL,并下载网页内容,将 HTML 放入 html_queue
def do_craw(url_queue: queue.Queue, html_queue: queue.Queue):
    while True:
        # 从 URL 队列中获取一个 URL
        url = url_queue.get()  # get() 会阻塞,直到队列中有元素可取
        # 调用 blog_spider 模块中的 craw 函数下载网页内容
        html = blog_spider.craw(url)
        # 将下载的 HTML 放入 html_queue 队列中
        html_queue.put(html)
        # 打印日志,显示当前线程正在处理的 URL 以及剩余的 URL 数量
        print(threading.current_thread().name, f"craw {url}", "url_queue.size=", url_queue.qsize())
        # 随机等待 1 到 2 秒,模拟爬虫访问间隔,避免对服务器造成过大压力
        time.sleep(random.randint(1, 2))

# 消费者线程:负责从 html_queue 中取出 HTML 内容,并解析数据,写入文件
def do_parse(html_queue: queue.Queue, fout):
    while True:
        # 从 HTML 队列中获取一个 HTML 内容
        html = html_queue.get()
        # 使用 blog_spider 模块中的 parse 函数解析网页内容
        results = blog_spider.parse(html)
        # 将解析出的结果写入文件,每一行一个结果
        for result in results:
            fout.write(str(result) + "\n")
        # 打印日志,显示当前线程解析到的结果数量以及剩余的 HTML 内容数量
        print(threading.current_thread().name, f"results.size", len(results), "html_queue_size=", html_queue.qsize())
        # 随机等待 1 到 2 秒,模拟处理时间,避免过快操作
        time.sleep(random.randint(1, 2))

# 主程序:负责初始化队列和线程
if __name__ == '__main__':
    # 创建两个队列:一个用于存放待爬取的 URL,另一个用于存放下载的 HTML 内容
    url_queue = queue.Queue()
    html_queue = queue.Queue()

    # 将 blog_spider 模块中的 URL 列表添加到 url_queue 中
    for url in blog_spider.urls:
        url_queue.put(url)  # 将每个 URL 放入队列中

    # 开启 3 个生产者线程,每个线程负责从 url_queue 中取 URL 并下载网页
    for idx in range(3):
        t = threading.Thread(target=do_craw, args=(url_queue, html_queue), name=f"craw{idx}")
        t.start()  # 启动线程

    # 打开一个文件用于保存爬取的数据
    fout = open("spider_data.txt", "w")

    # 开启 2 个消费者线程,每个线程负责从 html_queue 中取出 HTML 内容并解析数据
    for idx in range(2):
        t = threading.Thread(target=do_parse, args=(html_queue, fout), name=f"parse{idx}")
        t.start()  # 启动线程

下面是代码运行时产出的结果: 

 

 

 

 

到这里可以看到代码已经输出完毕,这时我们打开该爬虫创建的文件,就可以看到我们爬取的内容了,如下图所示:

 到这里我们就实现了一次简单爬虫的应用,通过写一个爬虫的代码模块,然后通过外部调用将其爬取的内容保存到相应的文件中,方便我们查看。


http://www.kler.cn/a/401897.html

相关文章:

  • Vue3 虚拟列表组件库 virtual-list-vue3 的使用
  • uni-app快速入门(十)--常用内置组件(下)
  • 掌握SEO提升网站流量的关键在于长尾关键词的有效运用
  • stm32启动过程解析startup启动文件
  • 搭建MC服务器
  • 内网安全隧道搭建-ngrok-frp-nps-sapp
  • 小程序-基于java+SpringBoot+Vue的小区服务管理系统设计与实现
  • 力扣-Hot100-链表其三【算法学习day.36】
  • 初识arkts-类-接口
  • 关于php Datetime 时区转换因为timezone_version(时区版本)问题造成的时区转换问题
  • k8s默认使用的后端网络模式
  • 基于YOLOv8深度学习的智慧社区建筑外墙破损(裂缝、露筋、剥落)检测系统研究与实现(PyQt5界面+数据集+训练代码)
  • 【Pikachu】PHP反序列化RCE实战
  • Django数据库迁移与反向迁移处理方案分析
  • C#使用App.config读写配置键值的简单示例
  • E45.【C语言】练习:输入10个整数查找找并打印不相同的数字及个数
  • 测试杂文 - linux串口打印
  • Rust宏系列教程—自定义派生宏
  • uniapp开发的陪玩系统该如何实现后端PHP语言的书写?
  • Android集成FCM(Firebace Cloud Messaging )
  • 9.《滑动窗口篇》---①长度最小的子数组(中等)
  • Elasticsearch 查看磁盘占用 查看指定索引磁盘占用
  • SpringBoot 2.2.10 无法执行Test单元测试
  • Excel数据动态获取与映射
  • MySQL SELECT 语句执行链路解析
  • C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程