用Python爬取东方财富网上市公司财务报表_东方财富网 舆情评分系统 python代码

13element = browser.find_element_by_css_selector(‘#dt_1’)  # 定位表格,element是WebElement类型
14# 提取表格内容td
15td_content = element.find_elements_by_tag_name(“td”) # 进一步定位到表格内容所在的td节点
16lst = []  # 存储为list
17for td in td_content:
18    lst.append(td.text)
19print(lst) # 输出表格内容


这里,使用Chrome浏览器构造一个Webdriver对象,赋值给变量browser,browser调用get()方法请求想要抓取的网页。接着使用`find_element_by_css_selector`方法查找表格所在的节点:**'#dt\_1'**。


这里推荐一款小巧、快速定位css/xpath的Chrome插件:**SelectorGadget**,使用这个插件就不用再去源代码中手动定位节点那么麻烦了。


插件地址:https://chrome.google.com/webstore/detail/selectorgadget/mhjhnkcfbdhnjickkkdbjoemdmbfginb


紧接着再向下定位到**td**节点,因为网页中有很多个td节点,所以要用**find\_elements**方法。然后,遍历数据节点存储到list中。打印查看一下结果:


![](https://img-blog.csdn.net/20181020121326927?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


  



1# list形式:
2[‘1’, ‘002161’, ‘远望谷’, …‘-7960万’, ‘09-29’,
3 ‘2’,‘002316’, ‘亚联发展’, …‘1.79亿’, ‘09-29’, 
4 ‘3’,…
5 ‘50’, ‘002683’, ‘宏大爆破’,…‘1.37亿’, ‘09-01’]


是不是很方便,几行代码就能抓取下来这一页表格,除了速度有点慢。


为了便于后续存储,我们将list转换为DataFrame。首先需要把这一个大的list分割为多行多列的子list,实现如下:



1import pandas as pd
2# 确定表格列数
3col = len(element.find_elements_by_css_selector(‘tr:nth-child(1) td’))
4# 通过定位一行td的数量,可获得表格的列数,然后将list拆分为对应列数的子list
5lst = [lst[i:i + col] for i in range(0, len(lst), col)]
6# 原网页中打开"详细"链接可以查看更详细的数据,这里我们把url提取出来,方便后期查看
7lst_link = []
8links = element.find_elements_by_css_selector(‘#dt_1 a.red’)
9for link in links:
10    url = link.get_attribute(‘href’)
11    lst_link.append(url)
12lst_link = pd.Series(lst_link)
13# list转为dataframe
14df_table = pd.DataFrame(lst)
15# 添加url列
16df_table[‘url’] = lst_link
17print(df_table.head())  # 查看DataFrame


这里,要将list分割为子list,只需要确定表格有多少列即可,然后将每相隔这么多数量的值划分为一个子list。如果我们数一下该表的列数,可以发现一共有16列。但是这里不能使用这个数字,因为除了利润表,其他报表的列数并不是16,所以当后期爬取其他表格可能就会报错。这里仍然通过f**ind\_elements\_by\_css\_selector**方法,定位首行td节点的数量,便可获得表格的列数,然后将list拆分为对应列数的子list。同时,原网页中打开"详细"列的链接可以查看更详细的数据,这里我们把url提取出来,并增加一列到DataFrame中,方便后期查看。打印查看一下输出结果:


![](https://img-blog.csdn.net/20181020121355363?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


  


可以看到,表格所有的数据我们都抓取到了,下面只需要进行分页循环爬取就行了。


这里,没有抓取表头是因为表头有合并单元格,处理起来就非常麻烦。建议表格抓取下来后,在excel中复制表头进去就行了。如果,实在想要用代码完成,可以参考这篇文章:https://blog.csdn.net/weixin\_39461443/article/details/75456962


#### 4.3. 分页爬取


上面完成了单页表格的爬取,下面我们来实现分页爬取。


首先,我们先实现Selenium模拟翻页跳转操作,成功后再爬取每页的表格内容。



1from selenium import webdriver
2from selenium.common.exceptions import TimeoutException
3from selenium.webdriver.common.by import By
4from selenium.webdriver.support import expected_conditions as EC
5from selenium.webdriver.support.wait import WebDriverWait
6import time
7
8browser = webdriver.Chrome()
9browser.maximize_window()  # 最大化窗口,可以选择设置
10wait = WebDriverWait(browser, 10)
11def index_page(page):
12    try:
13        browser.get(‘http://data.eastmoney.com/bbsj/201806/lrb.html’)
14        print(‘正在爬取第: %s 页’ % page)
15        wait.until(
16            EC.presence_of_element_located((By.ID, “dt_1”)))
17        # 判断是否是第1页,如果大于1就输入跳转,否则等待加载完成。
18        if page > 1:
19            # 确定页数输入框
20            input = wait.until(EC.presence_of_element_located(
21                (By.XPATH, ‘//*[@id=“PageContgopage”]’)))
22            input.click()
23            input.clear()
24            input.send_keys(page)
25            submit = wait.until(EC.element_to_be_clickable(
26                (By.CSS_SELECTOR, ‘#PageCont > a.btn_link’)))
27            submit.click()
28            time.sleep(2)
29        # 确认成功跳转到输入框中的指定页
30        wait.until(EC.text_to_be_present_in_element(
31            (By.CSS_SELECTOR, ‘#PageCont > span.at’), str(page)))
32    except Exception:
33        return None
34
35def main():
36    for page in range(1,5):  # 测试翻4页
37        index_page(page)
38if name == ‘main’:
39    main()


这里,我们先加载了相关包,使用WebDriverWait对象,设置最长10s的显式等待时间,以便网页加载出表格。判断表格是否加载出来,用到了**EC.presence\_of\_element\_located**条件。表格加载出来后,设置一个页面判断,如果在第1页就等待页面加载完成,如果大于第1页就开始跳转。


要完成跳转操作,我们需要通过获取输入框input节点,然后用clear()方法清空输入框,再通过send\_keys()方法填写相应的页码,接着通过submit.click()方法击下一页完成翻页跳转。


这里,我们测试一下前4页跳转效果,可以看到网页成功跳转了。下面就可以对每一页应用第一页爬取表格内容的方法,抓取每一页的表格,转为DataFrame然后存储到csv文件中去。


![](https://img-blog.csdn.net/20181020121448160?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


  


#### 4.4. 通用爬虫构造


上面,我们完成了**2018年中报利润表: http://data.eastmoney.com/bbsj/201806/lrb.html**,一个网页表格的爬取。但如果我们想爬取任意时期、任意一张报表的表格,比如2017年3季度的利润表、2016年全年的业绩报表、2015年1季度的现金流量表等等。上面的代码就行不通了,下面我们对代码进行一下改造,变成更通用的爬虫。从图中可以看到,东方财富网年报季报有7张表格,财务报表最早从2007年开始每季度一次。基于这两个维度,可重新构造url的形式,然后爬取表格数据。下面,我们用代码进行实现:


![](https://img-blog.csdn.net/20181020121535718?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


  



1# 重构url
2# 1 设置财务报表获取时期
3year = int(float(input('请输入要查询的年份(四位数2007-2018):  ')))
4# int表示取整,里面加float是因为输入的是str,直接int会报错,float则不会
5while (year < 2007 or year > 2018):
6    year = int(float(input(‘年份数值输入错误,请重新输入:’)))
7quarter = int(float(input('请输入小写数字季度(1:1季报,2-年中报,3:3季报,4-年报):  ')))
8while (quarter < 1 or quarter > 4):
9    quarter = int(float(input('季度数值输入错误,请重新输入:  ')))
10# 转换为所需的quarter 两种方法,2表示两位数,0表示不满2位用0补充
11quarter = ‘{:02d}’.format(quarter * 3)
12# quarter = ‘%02d’ %(int(month)*3)
13date = ‘{}{}’ .format(year, quarter)
14
15# 2 设置财务报表种类
16tables = int(
17    input('请输入查询的报表种类对应的数字(1-业绩报表;2-业绩快报表:3-业绩预告表;4-预约披露时间表;5-资产负债表;6-利润表;7-现金流量表):  '))
18dict_tables = {1: ‘业绩报表’, 2: ‘业绩快报表’, 3: ‘业绩预告表’,
19               4: ‘预约披露时间表’, 5: ‘资产负债表’, 6: ‘利润表’, 7: ‘现金流量表’}
20dict = {1: ‘yjbb’, 2: ‘yjkb/13’, 3: ‘yjyg’,
21        4: ‘yysj’, 5: ‘zcfz’, 6: ‘lrb’, 7: ‘xjll’}
22category = dict[tables]
23
24# 3 设置url
25url = ‘http://data.eastmoney.com/{}/{}/{}.html’ .format(‘bbsj’, date, category)
26print(url)  # 测试输出的url


 


![](https://img-blog.csdn.net/20181020121639458?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


  


经过上面的设置,我们通过输入想要获得指定时期、制定财务报表类型的数值,就能返回相应的url链接。将该链接应用到前面的爬虫中,就可以爬取相应的报表内容了。


另外,除了从第一页开始爬取到最后一页的结果以外,我们还可以自定义设置想要爬取的页数。比如起始页数从第1页开始,然后爬取10页。



1# 4 选择爬取页数范围
2start_page = int(input(‘请输入下载起始页数:\n’))
3nums = input(‘请输入要下载的页数,(若需下载全部则按回车):\n’)
4# 确定网页中的最后一页
5browser.get(url)
6# 确定最后一页页数不直接用数字而是采用定位,因为不同时间段的页码会不一样
7try:
8    page = browser.find_element_by_css_selector(‘.next+ a’)  # next节点后面的a节点
9except:
10    page = browser.find_element_by_css_selector(‘.at+ a’)
11else:
12    print(‘没有找到该节点’)
13# 上面用try.except是因为绝大多数页码定位可用’.next+ a’,但是业绩快报表有的只有2页,无’.next+ a’节点
14end_page = int(page.text)
15
16if nums.isdigit():
17    end_page = start_page + int(nums)
18elif nums == ‘’:
19    end_page = end_page
20else:
21    print(‘页数输入错误’)
22# 输入准备下载表格类型
23print(‘准备下载:{}-{}’ .format(date, dict_tables[tables]))


经过上面的设置,我们就可以实现自定义时期和财务报表类型的表格爬取了,将代码再稍微整理一下,可实现下面的爬虫效果:


视频截图:


![](https://img-blog.csdn.net/20181020121707353?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


背景中类似黑客帝国的代码雨效果,其实是动态网页效果。


 


这里,我下载了所有上市公司的部分报表。


2018年中报业绩报表:


![](https://img-blog.csdn.net/20181020121821103?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXNvbmd6aXll/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


  


2017年报的利润表:




### 最后

> **🍅 硬核资料**:关注即可领取PPT模板、简历模板、行业经典书籍PDF。  
> **🍅 技术互助**:技术群大佬指点迷津,你的问题可能不是问题,求资源在群里喊一声。  
> **🍅 面试题库**:由技术群里的小伙伴们共同投稿,热乎的大厂面试真题,持续更新中。  
> **🍅 知识体系**:含编程语言、算法、大数据生态圈组件(Mysql、Hive、Spark、Flink)、数据仓库、Python、前端等等。




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值