Web Spider NEX XX国际货币经纪 - PDF下载 & 解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 一、任务说明1.PDF下载提示:下载2019年1月1日-至今的"银行间货币市场"PDF文件

Web Spider NEX XX国际货币经纪 - PDF下载 & 解析


首先声明: 此次案例只为学习交流使用,切勿用于其他非法用途


文章目录

前言

一、任务说明

1.PDF下载

2.PDF解析提取关键词数据

二、Pip模块安装

三、网站分析

四、核心代码注释

1.创建2019年1月1日-至今的时间字符串,存入列表中

2.pdf下载

3.pdf读取解析

五、运行结果

六、示例代码

总结

前言

目标网站:https://www.cfets-nex.com.cn/
在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、任务说明

1.PDF下载

提示:下载2019年1月1日-至今的"银行间货币市场"PDF文件
下图网址:https://www.cfets-nex.com.cn/Market/marketOverview/dailyReview
在这里插入图片描述
在这里插入图片描述

2.PDF解析提取关键词数据

提取关键词数据说明

  • 提取下图标红框处位置的内容,如果不存在则赋值"None";
  • 红框处1:以"今日资金面"开头,句号(。)结束;
  • 红框处2:以"资金面情绪指数"开头,换行(\n)结束;
  • 以上为主要的提取部分,有些开头的关键词不同,需要另外写点匹配规则,参考案例;

提示:如果有更好的提取方式可以在评论处留言或者私信我,让我们在IT社区平台共同进步,感谢!
在这里插入图片描述

二、Pip模块安装

镜像地址

案例使用到的模块以及对应版本

  • pandas==1.1.3
  • PyPDF2==2.12.1
  • requests==2.27.0

pip指定模块安装:pip install 模块名 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip指定requirements.txt文件安装:pip install -i https://pypi.doubanio.com/simple/ -r requirements.txt

三、网站分析

1、打开链接,可以发现一个规律,每天收盘日评的网站链接是由相应的日期字符串组成;
链接后面的时间字符串为:2022/12/15
在这里插入图片描述
链接后面的时间字符串为:2022/12/16
在这里插入图片描述2、按F12进入开发者模式,可以直接看到PDF的链接,直接请求网站就完事了;在这里插入图片描述
标签a的href:/Cms_Data/Contents/Site2019/Folders/Daily/~contents/XBVJCVJ4Q8QG9A9L/MM.pdf
根据经验前缀需要加上:https://www.cfets-nex.com.cn
组合后可以直接打开PDF:https://www.cfets-nex.com.cn/Cms_Data/Contents/Site2019/Folders/Daily/~contents/XBVJCVJ4Q8QG9A9L/MM.pdf
在这里插入图片描述

四、核心代码注释

1.创建2019年1月1日-至今的时间字符串,存入列表中

import datetime
start_string = '2019-01-01'
def create_date_list():
    start_date = datetime.datetime.strptime(start_string , "%Y-%m-%d")  # 将指定的字符串转为时间格式
    now_date = (datetime.datetime.now()).strftime("%Y-%m-%d")  # 获取当前的时间
    date_string_list = list()
    i = 0
    while True:
        date_i = (start_date + datetime.timedelta(days=i)).strftime('%Y-%m-%d')
        date_string = str(date_i).replace('-', '/')
        print("创建时间字符串 - 存储成功:", date_string)
        date_string_list.append(date_string)
        if date_i < now_date:
            i += 1
        else:
            break
    return date_string_list

2.pdf下载

import requests
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
def pdf_download():
    file_path = "result.pdf"
    pdf_url = 'https://xxxx.pdf'
    response = requests.get(url=pdf_url, headers=headers, timeout=5)
    with open(file_path, 'wb') as fis:
        for chunk in response.iter_content(chunk_size=1000):
            fis.write(chunk)
            fis.flush()
        print(f'下载完成:{file_path}')
    return True

3.pdf读取解析

import PyPDF2
pdffile = open(file=file_path, mode='rb')  # 读取pdf文件;
pdfreader = PyPDF2.PdfFileReader(pdffile)
pdf_content = ''
for i in range(pdfreader.numPages):  # 获取pdf的总页数;
    page_content = pdfreader.getPage(i)  # 获取第i页的对象;
    pdf_content += page_content.extractText()  # 提取第i页的对象内容,字符串类型;
parse(pdf_content) # 自定义一个解析内容的方法,根据自己的需求提取相应的内容;

五、运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、示例代码

import os
import re
import time
import PyPDF2
import datetime
import requests
import pandas as pd
from requests import exceptions as request_exceptions


class SHICEconomy(object):
    def __init__(self):
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/95.0.4638.69 Safari/537.36'
        }
        self.start_string = '2019-01-01'
        self.resource_path = 'resource'
        self.result_file_path = 'result.csv'

    def create_date_list(self):
        start_date = datetime.datetime.strptime(self.start_string, "%Y-%m-%d")  # 将指定的字符串转为时间格式
        now_date = (datetime.datetime.now()).strftime("%Y-%m-%d")  # 获取当前的时间
        date_string_list = list()
        i = 0
        while True:
            date_i = (start_date + datetime.timedelta(days=i)).strftime('%Y-%m-%d')
            date_string = str(date_i).replace('-', '/')
            print("创建时间字符串 - 存储成功:", date_string)
            date_string_list.append(date_string)
            if date_i < now_date:
                i += 1
            else:
                break
        return date_string_list

    def request_server(self, url):
        request_count = 0
        request_total = 3
        result = {'status': False}
        while request_count < request_total:
            try:
                response = requests.get(url=url, headers=self.headers, timeout=5)
                result = {'status': True, 'response': response}
                break
            except request_exceptions.ConnectTimeout:
                print(f'{url} - 请求失败 ConnectTimeout!\n', end='')
            except request_exceptions.RequestException:
                print(f'{url} - 请求失败 RequestException!\n', end='')
            request_count += 1
            time.sleep(1)
        return result

    def pdf_download(self, file_path, pdf_url):
        """ pdf下载 """
        download_result = {'status': False}
        request_result = self.request_server(url=pdf_url)
        if request_result['status'] is False:
            return download_result
        response = request_result['response']
        with open(file_path, 'wb') as fis:
            for chunk in response.iter_content(chunk_size=1000):
                fis.write(chunk)
                fis.flush()
            print(f'下载完成:{file_path}')
        download_result = {'status': True}
        return download_result

    def read_finished_download_path(self):
        finished_download_pdf_list = list()
        for path in os.listdir(self.resource_path):
            file_path = f'{self.resource_path}/{path}'
            finished_download_pdf_list.append(file_path)
        return finished_download_pdf_list

    def pdf_download_controller(self, date_string_list=[]):
        """ pdf下载控制 """
        finished_download_pdf_list = self.read_finished_download_path()  # 获取已经下载的pdf地址
        for date_string in date_string_list:
            file_path = f"{self.resource_path}/{date_string.replace('/', '-')}.pdf"  # 拼接下载文件路径
            if file_path in finished_download_pdf_list:
                print(f"已下载:{file_path}")
                continue
            url = f'https://www.cfets-nex.com.cn/Market/marketOverview/dailyReview?Date={date_string}'
            request_result = self.request_server(url=url)
            if request_result['status'] is False:  # pdf请求状态
                print(f"请求失败:{url}")
                continue
            html_text = request_result['response'].text
            pdf_re = re.search(pattern="银行间货币市场.*?href='(.*?)'", string=html_text, flags=re.S)  # 匹配pdf下载地址
            pdf_prefix = 'https://www.cfets-nex.com.cn'
            if pdf_re is None:
                print(f"当天无数据(或还未发布数据):{url}")
                continue
            else:
                pdf_suffix = pdf_re.group(1)
            pdf_url = pdf_prefix + pdf_suffix
            download_result = self.pdf_download(file_path, pdf_url)  # 下载pdf
            if download_result['status'] is False:  # pdf下载状态
                print(f"下载失败:{url}")
                continue
            finished_download_pdf_list.append(file_path)  # 存储下载成功之后的文件地址
        return finished_download_pdf_list

    def pdf_parse(self, pdf_path_list):
        for file_path in pdf_path_list:
            column1_content = file_path.split('/')[-1].split('.pdf')[0]
            try:
                pdffile = open(file=file_path, mode='rb')  # 读取pdf文件
                pdfreader = PyPDF2.PdfFileReader(pdffile)
            except Exception:
                content = f"{column1_content},None,None\n"
                self.csv_save(content)
                print(f"{file_path} - PDF读取异常")
                continue
            pdf_content = ''
            for i in range(pdfreader.numPages):  # 获取pdf的总页数
                page_content = pdfreader.getPage(i)  # 获取第i页的对象
                pdf_content += page_content.extractText()  # 提取第i页的对象内容
            column2_1_re = re.search(pattern='今.{0,1}资金面(.*?)。', string=pdf_content, flags=re.S)
            column2_2_re = re.search(pattern='早盘资金面(.*?)。', string=pdf_content, flags=re.S)
            if column2_1_re:
                column2_content = f'{column2_1_re.group()}'.replace('\n', '').replace(',', ',')
            elif column2_2_re:
                column2_content = f'{column2_2_re.group()}'.replace('\n', '').replace(',', ',')
            else:
                column2_content = 'None'
            column3_1_re = re.search(pattern='资金面情绪指数(.*?)\n', string=pdf_content, flags=re.S)
            column3_2_re = re.search(pattern='今日全天的资金面指数(.*?)\n', string=pdf_content, flags=re.S)
            column3_3_re = re.search(pattern='今日资金.{0,1}情绪指数(.*?)\n', string=pdf_content, flags=re.S)
            column3_4_re = re.search(pattern='情绪指数(.*?)\n', string=pdf_content, flags=re.S)
            if column3_1_re:
                column3_content = f'资金面情绪指数{column3_1_re.group(1)}'.replace('\n', '').replace(',', ',')
            elif column3_2_re:
                column3_content = f'今日全天的资金面指数{column3_2_re.group(1)}。'.replace('\n', '').replace(',', ',')
            elif column3_3_re:
                column3_content = f'{column3_3_re.group()}'.replace('\n', '').replace(',', ',')
            elif column3_4_re:
                column3_content = f'{column3_4_re.group()}'.replace('\n', '').replace(',', ',')
            else:
                column3_content = 'None'
            content = f"{column1_content},{column2_content},{column3_content}\n"
            self.csv_save(content)
            print("写入成功:", column1_content, column2_content, column3_content)
        return True

    def create_file(self):
        if os.path.exists(self.resource_path) is False:
            os.mkdir(self.resource_path)
        with open(file=self.result_file_path, mode='w', encoding='utf-8') as fis:
            fis.write('日期,今日资金面,资金面情绪指数\n')

    def csv_save(self, content):
        with open(file=self.result_file_path, mode='a+', encoding='utf-8') as fis:
            fis.write(content)

    def csv_save_as_xlsx(self):
        """ 读取csv文件将结果写入xlsx """
        filename_prefix = os.path.splitext(self.result_file_path)[0]  # 切割文件路径以及后缀
        df = pd.read_csv(self.result_file_path, encoding='utf-8', dtype='object')
        df.to_excel(f"{filename_prefix}.xlsx", index=False)
        print("csv 转 xlsx 成功!")

    def runs(self):
        self.create_file()
        date_string_list = self.create_date_list()
        pdf_path_list = self.pdf_download_controller(date_string_list)
        self.pdf_parse(pdf_path_list)
        self.csv_save_as_xlsx()


if __name__ == '__main__':
    SHICEconomy().runs()

总结

此次案例只为学习交流使用,若有侵犯网站利益的地方请及时联系我下架该博文;
在此我抛出两个问题,欢迎在评论区讨论或者私信我,感谢赐教!:
问题1:如何通过requests请求pdf链接拿到二进制内容后直接使用pdf解析模块进行解析;
问题2:如何以更好的方式提取pdf的关键词内容;

目录
相关文章
|
11天前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
41 0
|
11天前
|
Java 数据库 API
JSF与JPA的史诗级联盟:如何编织数据持久化的华丽织锦,重塑Web应用的荣耀
【8月更文挑战第31天】JavaServer Faces (JSF) 和 Java Persistence API (JPA) 分别是构建Java Web应用的用户界面组件框架和持久化标准。结合使用JSF与JPA,能够打造强大的数据驱动Web应用。首先,通过定义实体类(如`User`)和配置`persistence.xml`来设置JPA环境。然后,在JSF中利用Managed Bean(如`UserBean`)管理业务逻辑,通过`EntityManager`执行数据持久化操作。
21 0
|
11天前
|
前端开发 开发者 Apache
揭秘Apache Wicket项目结构:如何打造Web应用的钢铁长城,告别混乱代码!
【8月更文挑战第31天】Apache Wicket凭借其组件化设计深受Java Web开发者青睐。本文详细解析了Wicket项目结构,帮助你构建可维护的大型Web应用。通过示例展示了如何使用Maven管理依赖,并组织页面、组件及业务逻辑,确保代码清晰易懂。Wicket提供的页面继承、组件重用等功能进一步增强了项目的可维护性和扩展性。掌握这些技巧,能够显著提升开发效率,构建更稳定的Web应用。
34 0
|
11天前
|
UED 存储 自然语言处理
【语言无界·体验无疆】解锁Vaadin应用全球化秘籍:从代码到文化,让你的应用畅游世界每一个角落!
【8月更文挑战第31天】《国际化与本地化实战:构建多语言支持的Vaadin应用》详细介绍了如何使用Vaadin框架实现应用的国际化和本地化,提升用户体验和市场竞争力。文章涵盖资源文件的创建与管理、消息绑定与动态加载、日期和数字格式化及文化敏感性处理等方面,通过具体示例代码和最佳实践,帮助开发者构建适应不同语言和地区设置的Vaadin应用。通过这些步骤,您的应用将更加灵活,满足全球用户需求。
25 0
|
11天前
|
开发者 Java
Play Framework深度解析:依赖注入的神秘力量,如何助力Web应用架构优化?答案即将揭晓!
【8月更文挑战第31天】依赖注入(DI)是现代软件开发的关键技术,用于分离对象创建与依赖关系,提升代码的可维护性和可测试性。Play Framework是一款高性能Java Web框架,内置了基于Google Guice的DI支持。本文探讨Play Framework中DI的最佳实践,包括定义组件、构造函数注入、字段注入以及作用域控制和自定义绑定等高级特性,帮助开发者轻松构建结构清晰、可维护性高的Web应用。
23 0
|
11天前
|
API 数据库 UED
全面解析构建高性能API的秘诀:运用Entity Framework Core与异步编程提升Web应用响应速度及并发处理能力的详细指南与实践案例
【8月更文挑战第31天】本文详细介绍了如何利用 Entity Framework Core (EF Core)的异步编程特性构建高性能 API。通过创建基于 EF Core 的 .NET Core Web API 项目,配置数据库上下文,并定义领域模型,文章展示了如何使用异步方法进行数据查询、加载相关实体及事务处理。具体代码示例涵盖了 GET、POST、PUT 和 DELETE 操作,全面展示了 EF Core 异步编程的优势,有助于提升 API 的响应速度和处理能力。
21 0
|
11天前
|
前端开发 程序员 API
从后端到前端的无缝切换:一名C#程序员如何借助Blazor技术实现全栈开发的梦想——深入解析Blazor框架下的Web应用构建之旅,附带实战代码示例与项目配置技巧揭露
【8月更文挑战第31天】本文通过详细步骤和代码示例,介绍了如何利用 Blazor 构建全栈 Web 应用。从创建新的 Blazor WebAssembly 项目开始,逐步演示了前后端分离的服务架构设计,包括 REST API 的设置及 Blazor 组件的数据展示。通过整合前后端逻辑,C# 开发者能够在统一环境中实现高效且一致的全栈开发。Blazor 的引入不仅简化了 Web 应用开发流程,还为习惯于后端开发的程序员提供了进入前端世界的桥梁。
20 0
|
27天前
|
XML 缓存 JSON
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
96 0
|
30天前
|
Linux Python Windows
Python PDF文件转Word格式,只需要3秒(附打包)
Python PDF文件转Word格式,只需要3秒(附打包)
46 3
Python PDF文件转Word格式,只需要3秒(附打包)
|
13天前
|
移动开发 资源调度 JavaScript
Vue移动端网页(H5)预览pdf文件(pdfh5和vue-pdf)
这篇文章介绍了在Vue移动端网页中使用`pdfh5`和`vue-pdf`两个插件来实现PDF文件的预览,包括滚动查看、缩放、添加水印、分页加载、跳转指定页数等功能。
Vue移动端网页(H5)预览pdf文件(pdfh5和vue-pdf)

热门文章

最新文章

推荐镜像

更多