爬虫实战--爬取简单文字图片并保存到mongodb数据库

文章目录

  • 前言
  • 发现宝藏

前言

为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)

发现宝藏

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。

http://jhsjk.people.cn/testnew/result

import os
import re
from datetime import datetime
import requests
import json
from bs4 import BeautifulSoup
from pymongo import MongoClient
from tqdm import tqdm

class ArticleCrawler:
    def __init__(self, catalogues_url, card_root_url, output_dir, db_name='ren-ming-wang'):
        self.catalogues_url = catalogues_url
        self.card_root_url = card_root_url
        self.output_dir = output_dir
        self.client = MongoClient('mongodb://localhost:27017/')
        self.db = self.client[db_name]
        self.catalogues = self.db['catalogues']
        self.cards = self.db['cards']
        self.headers = {
            'Referer': 'https://jhsjk.people.cn/result?',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/119.0.0.0 Safari/537.36',
            'Cookie': '替换成你自己的',
        }

    # 发送带参数的get请求并获取页面内容
    def fetch_page(self, url, page):
        params = {
            'keywords': '',
            'isFuzzy': '0',
            'searchArea': '0',
            'year': '0',
            'form': '',
            'type': '0',
            'page': page,
            'origin': '全部',
            'source': '2',
        }
        response = requests.get(url, params=params, headers=self.headers)
        soup = BeautifulSoup(response.text, 'html.parser')
        return soup

    # 解析请求版面
    def parse_catalogues(self, json_catalogues):
        card_list = json_catalogues['list']
        for list in card_list:
            a_tag = 'article/'+list['article_id']
            card_url = self.card_root_url + a_tag
            card_title = list['title']
            updateTime = list['input_date']
            self.parse_cards(card_url, updateTime)
            date = datetime.now()
            catalogues_id = list['article_id']+'01'

            # 检查重复标题
            existing_docs = self.catalogues.find_one({'id': catalogues_id})
            if existing_docs is not None:
                print(f'版面id: {catalogues_id}【已经存在】')
                continue

            card_data = {
                'id': catalogues_id,
                'title': card_title,
                'page': 1,
                'serial': 1,
                # 一个版面一个文章
                'dailyId': '',
                'cardSize': 1,
                'subjectCode': '50',
                'updateTime': updateTime,
                'institutionnCode': '10000',
                'date': date,
                'snapshot': {

                }
            }
            self.catalogues.insert_one(card_data)
            print(f'版面id: {catalogues_id}【插入成功】')

    # 解析请求文章
    def parse_cards(self, url, updateTime):
        response = requests.get(url, headers=self.headers)
        soup = BeautifulSoup(response.text, "html.parser")
        try:
            title = soup.find("div", "d2txt clearfix").find('h1').text
        except:
            try:
                title = soup.find('h1').text
            except:
                print(f'【无法解析该文章标题】{url}')
        html_content = soup.find('div', 'd2txt_con clearfix')
        text = html_content.get_text()
        imgs = [img.get('src') or img.get('data-src') for img in html_content.find_all('img')]
        cleaned_content = self.clean_content(text)
        # 假设我们有一个正则表达式匹配对象match
        match = re.search(r'\d+', url)
        # 获取匹配的字符串
        card_id = match.group()
        date = datetime.now()
        if len(imgs) != 0:
            # 下载图片
            self.download_images(imgs, card_id)

        # 创建文档
        document = {
            'id': card_id,
            'serial': 1,
            'page': 1,
            'url' : url,
            'type': 'ren-ming-wang',
            'catalogueId': card_id + '01',
            'subjectCode': '50',
            'institutionCode': '10000',
            'updateTime': updateTime,
            'flag': 'true',
            'date': date,
            'title': title,
            'illustrations': imgs,
            'html_content': str(html_content),
            'content': cleaned_content
        }
        # 检查重复标题
        existing_docs = self.cards.find_one({'id': card_id})
        if existing_docs is None:
            # 插入文档
            self.cards.insert_one(document)
            print(f"文章id:{card_id}【插入成功】")
        else:
            print(f"文章id:{card_id}【已经存在】")

    # 文章数据清洗
    def clean_content(self, content):
        if content is not None:
            content = re.sub(r'\r', r'\n', content)
            content = re.sub(r'\n{2,}', '', content)
            # content = re.sub(r'\n', '', content)
            content = re.sub(r' {6,}', '', content)
            content = re.sub(r' {3,}\n', '', content)
            content = content.replace('<P>', '').replace('<\P>', '').replace('&nbsp;', ' ')
        return content

    # 下载图片
    def download_images(self, img_urls, card_id):
        # 根据card_id创建一个新的子目录
        images_dir = os.path.join(self.output_dir, card_id)
        if not os.path.exists(images_dir):
            os.makedirs(images_dir)
            downloaded_images = []
            for img_url in img_urls:
                try:
                    response = requests.get(img_url, stream=True)
                    if response.status_code == 200:
                        # 从URL中提取图片文件名
                        image_name = os.path.join(images_dir, img_url.split('/')[-1])
                        # 确保文件名不重复
                        if os.path.exists(image_name):
                            continue
                        with open(image_name, 'wb') as f:
                            f.write(response.content)
                        downloaded_images.append(image_name)
                        print(f"Image downloaded: {img_url}")
                except Exception as e:
                    print(f"Failed to download image {img_url}. Error: {e}")
            return downloaded_images
        # 如果文件夹存在则跳过
        else:
            print(f'文章id为{card_id}的图片文件夹已经存在')

    # 查找共有多少页
    def find_page_all(self, soup):
        # 查找<em>标签
        em_tag = soup.find('em', onclick=True)
        # 从onclick属性中提取页码
        if em_tag and 'onclick' in em_tag.attrs:
            onclick_value = em_tag['onclick']
            page_number = int(onclick_value.split('(')[1].split(')')[0])
            return page_number
        else:
            print('找不到总共有多少页数据')

    # 关闭与MongoDB的连接
    def close_connection(self):
        self.client.close()

    # 执行爬虫,循环获取多页版面及文章并存储
    def run(self):
        soup_catalogue = self.fetch_page(self.catalogues_url, 1)
        page_all = self.find_page_all(soup_catalogue)
        if page_all:
            for index in tqdm(range(1, page_all), desc='Page'):
            # for index in tqdm(range(1, 50), desc='Page'):
                soup_catalogues = self.fetch_page(self.catalogues_url, index).text
                # 解析JSON数据
                soup_catalogues_json = json.loads(soup_catalogues)
                self.parse_catalogues(soup_catalogues_json)
                print(f'======================================Finished page {index}======================================')

        self.close_connection()

if __name__ == "__main__":
    crawler = ArticleCrawler(
        catalogues_url='http://jhsjk.people.cn/testnew/result',
        card_root_url='http://jhsjk.people.cn/',
        output_dir='D:\\ren-ming-wang\\img'
    )
    crawler.run()  # 运行爬虫,搜索所有内容
    crawler.close_connection()  # 关闭数据库连接

在这里插入图片描述

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

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

相关文章

基于ESP8266 开发板(MCU)遥控小车

遥控小车 ​ 遥控界面 ​ 【项目源码】 第一版ESP8266 https://github.com/liyinchigithub/esp8266_car_webServerhttps://github.com/liyinchigithub/esp8266_car_webServer 第二版ESP32 GitHub - liyinchigithub/esp32-wroom-car: 嵌入式单片机 ESP32 Arduino 遥控小车&a…

《Python 网络爬虫简易速速上手小册》第7章:如何绕过反爬虫技术?(2024 最新版)

文章目录 7.1 识别和应对 CAPTCHA7.1.1 重点基础知识讲解7.1.2 重点案例&#xff1a;使用Tesseract OCR识别简单CAPTCHA7.1.3 拓展案例 1&#xff1a;使用深度学习模型识别复杂CAPTCHA7.1.4 拓展案例 2&#xff1a;集成第三方 CAPTCHA 解决服务 7.2 IP 轮换与代理的使用7.2.1 重…

荣获双强认证!玻色量子荣登投资界2023Venture50新芽榜数字科技50强

2024年1月16日&#xff0c;由清科创业&#xff08;1945.HK&#xff09;、投资界发起的2023Venture50评选结果成功揭晓&#xff01;此次评选包含风云榜与新芽榜TOP50&#xff0c;以及五大行业榜单。玻色量子作为量子计算领军企业&#xff0c;荣登新芽榜50强与数字科技50强双强榜…

如何将pdf转换成ppt?掌握这个方法就简单多了

有时候&#xff0c;PDF文件的布局和设计可能需要进行微调或重新排版&#xff0c;以适应PPT的特定格式和风格。那么怎么pdf怎么转ppt呢&#xff1f;为了更方便地对布局、字体、图像和其他元素进行编辑和调整&#xff0c;以符合PPT的需求&#xff0c;我们可以直接通过pdf在线转pp…

zabbix server/agent源码编译成rpm包(通用版-小白教程)

前言 工作环境需要用到很多信创的操作系统&#xff0c;zabbix agent2的官方没有现成的包可用&#xff0c;网上巴拉了一下找到zabbix agent2通用版编译成rpm包的方法 思路&#xff1a;假如当你有一批ky10_x86的机器需要配套的zabbix agent的rpm包&#xff0c;那就找一台ky10_x…

【Linux】linux自动化构建工具make/makefile

linux自动化构建工具make/makefile 一&#xff0c;makefile是什么二&#xff0c;如何写makefile三&#xff0c;文件的三个时间属性四&#xff0c;makefile的推导 一&#xff0c;makefile是什么 对于make和makefile&#xff0c;简单来说&#xff0c;make是一个命令&#xff0c;用…

全网第一篇把Nacos配置中心服务端讲明白的

入口 getServerConfig对应&#xff1a;ConfigQueryRequestHandler&#xfffd;getBatchServiceConfig对应&#xff1a;ConfigChangeBatchListenResponse&#xfffd;admin对应&#xff1a;ConfigController 我们重点就要2个&#xff0c;一个是服务端如何完成客户端获取配置请…

Springboot简单设计两级缓存

两级缓存相比单纯使用远程缓存&#xff0c;具有什么优势呢&#xff1f; 本地缓存基于本地环境的内存&#xff0c;访问速度非常快&#xff0c;对于一些变更频率低、实时性要求低的数据&#xff0c;可以放在本地缓存中&#xff0c;提升访问速度 使用本地缓存能够减少和Redis类的远…

你知道网页采集工具吗?

一、网页采集器的定义和作用 网页采集器是一种自动化工具,用于从互联网上获取信息并将其保存到本地或远程数据库中。其作用在于帮助用户快速、自动地收集并整理网络上的信息,提高工作效率并且节省时间成本。网页采集器通过模拟人工浏览网页的行为,访问并提取目标网页的数据…

L1-037 A除以B-java

输入样例1&#xff1a; -1 2输出样例1&#xff1a; -1/2-0.50输入样例2&#xff1a; 1 -3输出样例2&#xff1a; 1/(-3)-0.33输入样例3&#xff1a; 5 0输出样例3&#xff1a; 5/0Error java import java.util.*; class Main{public static void main(String[] args){Sc…

机器学习中常用的性能度量—— ROC 和 AUC

什么是泛化能力&#xff1f; 通常我们用泛化能力来评判一个模型的好坏&#xff0c;通俗的说&#xff0c;泛化能力是指一个机器学期算法对新样本&#xff08;即模型没有见过的样本&#xff09;的举一反三的能力&#xff0c;也就是学以致用的能力。 举个例子&#xff0c;高三的…

BUUCTF-Real-[ThinkPHP]IN SQL INJECTION

目录 漏洞描述 漏洞分析 漏洞复现 漏洞描述 漏洞发现时间&#xff1a; 2018-09-04 CVE 参考&#xff1a;CVE-2018-16385 最高严重级别&#xff1a;低风险 受影响的系统&#xff1a;ThinkPHP < 5.1.23 漏洞描述&#xff1a; ThinkPHP是一款快速、兼容、简单的轻量级国产P…

Stable Diffusion 模型下载:ReV Animated

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十下载地址模型介绍 该模型能够创建 2.5D 类图像生成。此模型是检查点合并,这意味着它是其他模型的产物,以创建从原始模型派生的产品。 条目内容类型大模型

游戏视频录制软件推荐,打造专业电竞视频(3款)

随着游戏产业的快速发展&#xff0c;越来越多的玩家开始关注游戏视频录制软件。一款好的录制软件不仅可以帮助玩家记录游戏中的精彩瞬间&#xff0c;还可以让其与他人分享自己的游戏体验。接下来&#xff0c;我们将介绍三款热门的游戏视频录制软件&#xff0c;并对其进行详细的…

pwn学习笔记(2)

pwn学习笔记&#xff08;2&#xff09; 1.三种常见的寄存器&#xff1a; ​ ax寄存器&#xff1a;通用寄存器&#xff0c;可用于存放多种数据 ​ bp寄存器&#xff1a;存放的是栈帧的栈底地址 ​ sp寄存器&#xff1a;存放的是栈顶的地址 2.栈帧与栈工作的简介&#xff1a…

arping交叉编译

arping命令依赖libpcap和libnet&#xff0c;需要先交叉编译这两个库。 1.交叉编译libpcap 下载libpcap源文件&#xff0c;从github上克隆: git clone https://github.com/the-tcpdump-group/libpcap.git source交叉编译环境 # environment-setup是本机的交叉编译环境, 里面…

Centos7配置登录失败处理导致root被锁定处理办法

1、应用场景 root用户被系统锁定&#xff0c;无法登录系统。 2、问题现象 root锁定无法登录系统 3、原因 设置登录失败处理并对root用户生效&#xff0c;一直尝试错误的root密码或暴力破解root密码&#xff0c;导致无法自动解锁Linux的root账户 4、解决方案 1.将虚拟机开…

0 代码自动化测试:RF 框架实现企业级 UI 自动化测试

前言 现在大家去找工作&#xff0c;反馈回来的基本上自动化测试都是刚需&#xff01;没有自动化测试技能&#xff0c;纯手工测试基本没有什么市场。 但是很多人怕代码&#xff0c;觉得自动化测试就需要代码&#xff01;代码学习起来很难&#xff01; 当然代码学习不难&#xf…

重生奇迹MU如何挂机

1、重生奇迹MU觉醒哪里挂机经验多挂机收益最大化&#xff0c;在重生奇迹MU中玩家可以通过副本获得大量的经验和金币&#xff0c;甚至挂机也有不错的收益&#xff0c;对于玩家来说 2、卡利玛神庙、血色城堡、迷失之城、恶魔广场甚至是挂机自动刷怪&#xff0c;组队都会有经验加…

骑砍战团MOD开发(43)-顶点着色技术

一.顶点着色(vertex_color) 实际GPU渲染时有顶点着色和纹理着色两种方式,顶点着色消耗资源小,GPU将顶点颜色通过插值运算进行渲染.常用于同一物体的不同颜色渲染,如青苹果,红苹果,可以使用动态切换顶点颜色实现,而不通过设置纹理图片实现. Direct3D9中可声明灵活顶点格式 stru…