爬虫案例 --东方财富网股票

源码在底下 , 直接放源码审核不过 , 所以先啰嗦一点没用的东西

编写一个爬虫的基本实现思路可以概括为以下几个步骤。请注意,由于爬虫可能涉及法律和道德问题,特别是当它们用于未经授权地抓取网站数据时,因此在开始之前,请确保你的爬虫行为符合目标网站的robots.txt规则以及当地的法律法规。

1. 确定目标

  • 明确需求:确定你需要从哪些网站抓取哪些数据。
  • 分析网站结构:了解目标网站的页面结构,包括URL模式、页面元素等。

2. 编写爬虫框架

  • 选择编程语言:Python是编写爬虫的热门选择,因为它拥有强大的库支持,如requestsBeautifulSoupScrapy等。
  • 设置基础结构:创建一个基本的Python脚本,导入必要的库。

3. 发送HTTP请求

  • 使用requests库(或其他HTTP客户端库)发送GET或POST请求到目标URL。
  • 处理重定向和Cookies:确保爬虫能够处理重定向和保持会话状态(如登录状态)。
  • 设置请求头:模拟浏览器发送请求,设置合适的User-Agent和其他必要的请求头。

4. 解析HTML内容

  • 使用解析库:如BeautifulSouplxml等,解析HTML文档。
  • 提取数据:根据HTML结构,使用CSS选择器、XPath等方法提取所需数据。

5. 存储数据

  • 保存到文件:将抓取的数据保存为CSV、JSON等格式的文件。
  • 使用数据库:对于大量数据,可以考虑使用数据库(如MySQL、MongoDB)来存储。

6. 处理JavaScript渲染的页面

  • 如果目标网站大量使用JavaScript渲染页面内容,可能需要使用SeleniumPuppeteer(Node.js环境)等工具来模拟浏览器行为。

7. 遵守robots.txt规则和礼貌爬虫

  • 检查robots.txt:在开始抓取之前,检查目标网站的robots.txt文件,确保你的爬虫行为被允许。
  • 设置合理的请求间隔:避免过于频繁地发送请求,给目标网站服务器带来压力。
  • 处理反爬虫机制:如验证码、IP封锁等,可能需要采取额外的措施来绕过这些机制(但请注意,绕过某些反爬虫机制可能违反法律法规)。

8. 调试和优化

  • 调试:在开发过程中,使用打印语句、断点调试等方法来检查爬虫的行为是否符合预期。
  • 优化性能:对于大型网站或需要抓取大量数据的情况,优化爬虫的性能变得尤为重要。可以通过多线程/多进程、异步IO等方式来提高效率。
import csv  # 用于读写 CSV 文件
import json  # 用于解析 JSON 数据
import requests  # 用于发送 HTTP 请求
from lxml import etree  # 用于解析 HTML 文档


# 定义 DataScraper 类,实现数据抓取功能
class DataScraper:
    # 初始化函数
    def __init__(self):
        # 定义一个字典,用于存储页面名称和页面英文名称的对应关系
        self.pagename_type = {
            "业绩报表": "RPT_LICO_FN_CPD",
            "业绩快报": "RPT_FCI_PERFORMANCEE",
            "业绩预告": "RPT_PUBLIC_OP_NEWPREDICT",
            "预约披露时间": "RPT_PUBLIC_BS_APPOIN",
            "资产负债表": "RPT_DMSK_FN_BALANCE",
            "利润表": "RPT_DMSK_FN_INCOME",
            "现金流量表": "RPT_DMSK_FN_CASHFLOW"
        }

        self.pagename_en = {
            "业绩报表": "yjbb",
            "业绩快报": "yjkb",
            "业绩预告": "yjyg",
            "预约披露时间": "yysj",
            "资产负债表": "zcfz",
            "利润表": "lrb",
            "现金流量表": "xjll"
        }

        # 定义一个列表,用于存储英文列名
        self.en_list = []

        # 定义一个抓取数据的 URL
        self.url = 'https://datacenter-web.eastmoney.com/api/data/v1/get'

        # 定义请求头
        self.headers = {
            'Accept': '*/*',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Connection': 'closed',
            'Referer': 'https://data.eastmoney.com/',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
            'sec-ch-ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
            'sec-ch-ua-mobile': '?0',
            'sec-ch-ua-platform': '"Windows"'
        }

    # 定义一个函数,用于获取指定页面的表格数据
    def get_table(self, page):
        # 定义一个参数字典,用于传递抓取参数
        params = {
            'sortTypes': '-1,-1',  # 用于指定排序方式,这里设置为降序
            'reportName': self.table_type,  # 用于指定要抓取的报表类型
            'columns': 'ALL',  # 用于指定要抓取的列名
            'filter': f'(REPORT_DATE=\'{self.timePoint}\')'  # 用于指定查询条件,这里设置为查询指定日期范围的数据
        }

        # 如果要抓取的报表类型为 "RPT_LICO_FN_CPD",则需要修改查询条件
        if self.table_type in ['RPT_LICO_FN_CPD']:
            params['filter'] = f'(REPORTDATE=\'{self.timePoint}\')'

        # 添加分页参数
        params['pageNumber'] = str(page)

        # 使用 requests 库发送 GET 请求,获取数据
        response = requests.get(url=self.url, params=params, headers=self.headers)

        # 使用 json 模块解析响应数据
        data = json.loads(response.text)

        # 如果数据抓取成功,则返回数据
        if data['result']:
            return data['result']['data']
        else:
            return

    # 定义一个函数,用于获取指定页面的表头信息
    def get_header(self, all_en_list):
        # 创建一个空列表,用于存储中文列名
        ch_list = []

        # 定义一个页面的 URL
        url = f'https://data.eastmoney.com/bbsj/{self.pagename_en[self.pagename]}.html'

        # 使用 requests 库发送 GET 请求,获取页面数据
        response = requests.get(url)

        # 使用 lxml 模块解析 HTML 文档
        res = etree.HTML(response.text)

        # 遍历所有英文列名,获取对应的中文列名
        for en in all_en_list:
            ch = ''.join(
                [i.strip() for i in res.xpath(f'//div[@class="dataview"]//table[1]//th[@data-field="{en}"]//text()')])

            # 如果找到了中文列名,则将其添加到列表中
            if ch:
                ch_list.append(ch)
                # 将英文列名添加到列表中
                self.en_list.append(en)

        # 返回中文列名列表
        return ch_list

    # 定义一个函数,用于将抓取的数据写到 CSV 文件中
    def write_header(self, table_data):
        # 打开一个 CSV 文件,用于写数据
        with open(self.filename, 'w', encoding='utf-8', newline='') as f:
            # 创建一个 CSV 写器
            writer = csv.writer(f)
            # 获取表头信息
            headers = self.get_header(list(table_data[0].keys()))

            # 使用 CSV 写器写表头
            writer.writerow(headers)

    # 定义一个函数,用于将抓取的数据写到 CSV 文件中
    def write_table(self, table_data):
        # 打开一个 CSV 文件,用于追加写数据
        with open(self.filename, 'a', encoding='utf-8', newline='') as csvfile:
            # 创建一个 CSV 写器
            writer = csv.writer(csvfile)
            # 遍历所有数据,并将其写到 CSV 文件中
            for item in table_data:
                # 创建一个空列表,用于存储一行的数据
                row = []
                # 遍历所有列名,获取对应的数据
                for key in item.keys():
                    # 如果列名在英文列名列表中,则将其添加到列表中
                    if key in self.en_list:
                        row.append(str(item[key]))

                # 使用 CSV 写器写一行数据
                print(row)
                writer.writerow(row)

    # 定义一个函数,用于获取时间列表
    def get_timeList(self):
        # 定义一个请求头,用于模拟浏览器请求
        headers = {
            'Referer': 'https://data.eastmoney.com/bbsj/202312.html'
        }
        # 使用 requests 库发送 GET 请求,获取页面数据
        response = requests.get('https://data.eastmoney.com/bbsj/202312.html', headers=headers)

        # 使用 lxml 模块解析 HTML 文档
        res = etree.HTML(response.text)

        # 使用xpath获取时间列表
        return res.xpath('//*[@id="filter_date"]//option/text()')

    # 定义一个运行函数,用于启动数据抓取程序
    def run(self):
        # 使用 get_timeList 函数获取时间列表
        self.timeList = self.get_timeList()
        # 遍历时间列表,打印时间
        for index, value in enumerate(self.timeList):
            if (index + 1) % 5 == 0:
                print(value)
            else:
                print(value, end=' ; ')

        # 输入要抓取的时间点
        self.timePoint = str(input('\n请选择时间(可选项如上):'))
        # 输入要抓取的报表类型
        self.pagename = str(
            input('请输入报表类型(业绩报表;业绩快报;业绩预告;预约披露时间;资产负债表;利润表;现金流量表):'))

        # 判断输入的时间点和报表类型是否正确
        assert self.timePoint in self.timeList, '时间输入错误'
        assert self.pagename in list(self.pagename_type.keys()), '报表类型输入错误'

        # 根据输入的报表类型获取对应的表格类型



        self.table_type = self.pagename_type[self.pagename]
        self.filename = f'{self.pagename}_{self.timePoint}.csv'

        self.write_header(self.get_table(1))
        page = 1
        while True:
            table = self.get_table(page)
            if table:
                self.write_table(table)

            else:
                break
            page += 1


if __name__ == '__main__':
    scraper = DataScraper()
    scraper.run()

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

攒了一袋星辰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值