本文首发于我的博客:gongyanli.com
代码传送门:https://github.com/Gladysgong/cninfo
简书: https://www.jianshu.com/p/b5ef0e7e2b87
CSDN: https://mp.csdn.net/mdeditor/79759833

    首先说说我的目标把,就是抓取巨潮资讯网上一些上市农业企业的基本信息,主要是对页面的公司概况、高管人员、十大股东这几个板块的信
息进行抓取,如图。要抓取的上市农业企业的名单已经准备好了,但是同时要拿到的这些农业企业的url地址。本来考虑的是做一个整站提取url,
但是再想一想,这个网站包含了太多上市公司的信息,即使拿到了,也需要慢慢找。加上我们要抓取的农业企业不多,所以分析页面结果后,手动
整理他们的url,算是本爬虫的一个缺陷。

    巨潮资讯地址:http://www.cninfo.com.cn/information/companyinfo_n.html?brief?szmb000998上面这个就是公司概况的url地址,而高管人员只需要把brief换成management,十大股东只需要把brief换成shareholders,而后面的后缀
szmb000998这个是手动整理的,这个szmb没看出什么意思,后面的数字是当前公司的股票代码。经过分析,发现网页是动态加载的,里面的内容都是通过js来控制iframe进行展现的,通过scrapy中response.body获取网页的返回结果中,
没有完美所需要的内容,所以我们需要用selenium。

一、PhantomJS–PhantomJS安装验证

PhantomJS是一个基于webkit内核的没有界面的浏览器,所以它和chrome、Firefox这些没有什么差别,只是没有界面而已啦,所以并无高深之处。
关于它的安装及验证非常简单,大家可以参考我的另一篇文章,标题处去点击链接把。

二、Selenium–Selenium的使用

Selinium是一个自动化的测试工具,用它可以驱动浏览器执行特定的操作,比如点击按钮,切换到ifame中等操作,同时能够获取到浏览器渲染后的
源码。所以它对于那些用JavaScript渲染的网页来讲,Selenium是再合适不过了。
崔庆才的博客中有一篇详细讲解了Selenium的用法,可以参考。

三、通过Scrapy来使用Selenium

1.中间件

首先看一下我的工作目录把,没有什么特点,scrapy典型的工作目录,唯一不一样的是middlewares文件夹,里面存放的是我自定义的中间件。通过
自定义的中间件去把scrapy原本的中间件覆盖,从而用我们自己实现的功能去替换scrapy原有的功能。
我的中间件代码如下:打开PhantomJS浏览器,请求url地址,睡眠,接着切换iframe,因为我要获取的公司概况信息就在id='i_nr'的这个ifame
中,再睡眠,等待浏览器渲染出这个ifame中的内容,然后再body中保存此网页的源码,最后利用HtmlResponse把body传送离开。

`from selenium import webdriver
from scrapy.http import HtmlResponse
import timeclass JavaScriptMiddleware(object):def process_request(self, request, spider):if spider.name == 'CninfoSpider':print('PhantomJS1 is starting...')driver = webdriver.PhantomJS(executable_path=r'E:\Program Files\phantomjs-2.1.1-windows\bin\phantomjs.exe')driver.get(request.url)time.sleep(1)driver.switch_to.frame('i_nr')time.sleep(2)body = driver.page_sourceprint("访问:", request.url)return HtmlResponse(driver.current_url, body=body, encoding='utf-8')elif spider.name == 'CninfoManaSpider':print('PhantomJS2 is starting...')driver = webdriver.PhantomJS(executable_path=r'E:\Program Files\phantomjs-2.1.1-windows\bin\phantomjs.exe')driver.get(request.url)time.sleep(1)driver.switch_to.frame('i_nr')time.sleep(2)body = driver.page_sourceprint("访问:", request.url)return HtmlResponse(driver.current_url, body=body, encoding='utf-8')else:return

`

2.数据解析–cninfo.py

之后,我们就可以回到cninfo.py文件中对内容进行解析了。重写__init__,使用webdriver打开PhantomJS浏览器。重写start_requests方法,
拼接url,同时可以自定义返回函数parse。

`# --*-- coding:utf-8 -*-
import scrapy
from scrapy import Request
from scrapy.spiders import Spider
from selenium import webdriver
from ..items import AgriBasicItem# 巨潮资讯网--上市农业企业基本信息
class CninfoSpider(Spider):name = 'CninfoSpider'def __init__(self):self.broswer = webdriver.PhantomJS(executable_path=r'E:\Program Files\phantomjs-2.1.1-windows\bin\phantomjs.exe')self.broswer.set_page_load_timeout(30)def closed(self, spider):print('spider closed!')self.broswer.close()def start_requests(self):myurls = ['szmb000998', 'szsme002041', 'szsme002772', 'szcn300087', 'szcn300189', 'szcn300511','shmb600108','shmb600313', 'shmb600354', 'shmb600359','shmb600371', 'shmb600506', 'shmb600598', 'shmb601118', 'szmb000592', 'szsme002200','szsme002679','shmb600265', 'szmb000735', 'szsme002234','szsme002299', 'szsme002321', 'szsme002458', 'szsme002477', 'szsme002505', 'szsme002714','szsme002746', 'szcn300106', 'szcn300313', 'szcn300498','shmb600965', 'shmb600975', 'szmb000798', 'szsme002086', 'szsme002696', 'szmb200992','szcn300094','shmb600097', 'shmb600257', 'shmb600467', 'szmb000711', 'szmb000713']start_urls = [('http://www.cninfo.com.cn/information/companyinfo_n.html?brief?' + each) for each in myurls]for url in start_urls:yield Request(url=url, callback=self.parse)def parse(self, response):item = AgriBasicItem()item['full_name'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[1]/td[2]/text()').extract()[0]  # 公司名称item['en_name'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[2]/td[2]/text()').extract()[0]  # 英文名称item['cn_name'] = item['full_name']  # 中文名称item['nation'] = 'china'  # 国别item['address'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[3]/td[2]/text()').extract()[0]  # 注册地址item['established_time'] = None  # 成立时间item['stock_time'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[13]/td[2]/text()').extract()[0]  # 上市时间# shareholders = scrapy.Field()  # 主要股东item['industry'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[8]/td[2]/text()').extract()[0]  # 行业(经营类别)# managers = scrapy.Field()  # 主要管理人员item['parent_company'] = None  # 母公司item['subsidiaries'] = None  # 子公司item['offical_website'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[12]/td[2]/text()').extract()[0]  # 官网item['phone'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[10]/td[2]/text()').extract()[0]  # 公司电话item['fax'] = response.xpath('//div[@class="clear2"]/div[@class="zx_left"]/div[2]/table/tbody/tr[11]/td[2]/text()').extract()[0]  # 公司传真item['Twitter'] = None  # Twitteritem['stock_code'] = response.xpath('//div[@class="zx_info"]/form/table/tbody/tr/td[1]/text()').extract()[0]  # 股票代码item['abbr'] = response.xpath('//div[@class="zx_info"]/form/table/tbody/tr/td[1]/text()').extract()[1]  # 公司简称yield item`

3.数据持久化–pipelines.py

把抓取下来的数据存进mongo数据库,实现数据的持久化。setting中数据库配置如下:
MONGO_HOST = '127.0.0.1' # 主机ip
MONGO_PORT = 27017    # 端口号
MONGO_DB = 'agriEn'     # 数据库名称

`import pymongo
from scrapy.conf import settings
from .items import AgriBasicItem
from .items import AgriManaItemclass CninfoPipeline(object):def __init__(self):self.client = pymongo.MongoClient(host=settings['MONGO_HOST'], port=settings['MONGO_PORT'])self.db = self.client[settings['MONGO_DB']]self.cninfo_base = self.db['cninfo_base']self.cninfo_mana = self.db['cninfo_mana']self.cninfo_share = self.db['cninfo_share']def process_item(self, item, spider):if isinstance(item, AgriBasicItem):try:if item['full_name']:item = dict(item)self.cninfo_base.insert(item)print("insert baseinfo success !")return itemexcept Exception as e:spider.logger.exception("insert failed")elif isinstance(item,AgriManaItem):if item['managers']:item = dict(item)self.cninfo_mana.insert(item)print("insert managers success !")return item`

4.配置文件–setting.py

ROBOTSTXT_OBEY = FalseDOWNLOADER_MIDDLEWARES = {
# 键是中间件类的路径,值是中间的顺序
'cninfo.middlewares.middleware.JavaScriptMiddleware': 543,
# 禁止内置的中间件
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None }# 记得开启pipelines的调用
ITEM_PIPELINES = {
'cninfo.pipelines.CninfoPipeline': 300,}

四、缺陷

在这个爬虫中,其实出现了蛮多问题的,有些解决了,有些没有,记录一下,加深印象,还有感觉代码好垃圾。

1.缺陷1

上市农业企业的名字,以及名字的url链接手动整理的,因为只有40来个企业,所以才会用这个方法。本来是想通过Scarpy的CrawlSpider抓取,
抓取时通过Rule来控制所需要的农业企业,但是发现实在没有什么规律,只会把巨潮资讯上所有上市企业的url都获取下来,所以最后手动整理的
这40多个农业企业,希望日后能找到更简便的办法。

2.缺陷2

对于网页中的高管人员信息抓取中,本来是想思考放在一个爬虫中获取到的,但是仔细分析后发现,公司概况和高管人员分别对应着不同的url,
然后不同的url下再对应中动态加载iframe。url对比如下:
http://www.cninfo.com.cn/information/companyinfo_n.html?brief?szmb000998
http://www.cninfo.com.cn/information/companyinfo_n.html?management?szmb000998
这样子的话,就涉及到我需要在Selenuim中点击按钮,然后再渲染id='i_nr'的iframe,而且不同页面中iframe名字都叫i_nr。我试过这个
办法,但是拿回的源码并不是高管人员页面的源码,依然是公司概况页面的源码,也许是我方法用的不对,有待仔细研究。
所以我又在cninfo_mana.py中又写了一个爬虫,从而单独来获取高管人员页面的信息。

3.缺陷3

对于十大股东页面,按理说我应该在写一个py文件来单独获取它的页面信息,这样子就ok了,实际上我也是这么做的。但是爬虫运行是,却发
现我拿不到股东的信息,因为我发现当请求http://www.cninfo.com.cn/information/companyinfo_n.html?shareholders?
szmb000998时,首先切换到id='i_nr'的iframe中,但是随后股东的详细信息又在一个id='i_nr'的ifrma中,相当于这里有两个iframe,
我在中间件试了试两个这样子切换iframe,但是很遗憾我没拿到我想要的东西,源代码还是停留在第一层iframe中,所以最后我放弃了,没有
拿十大股东的信息,这个问题智能留着我以后解决了。

4.缺陷4

self.broswer = webdriver.PhantomJS(executable_path=r'E:\Program Files\phantomjs-2.1.1-windows\bin\phantomjs.exe')
这个代码在中间件和爬虫代码中都有,说明两次打开了浏览器,致使性能降低。

五、其他项目

    其实我之前还用Selenium写过一个项目,用过抓取FAO的国家分类信息,以前习惯不好,做事不记录,导致做完就忘,只有个模糊的印象。
今天把之前那个项目找到了,重新运行了一下,但是抓不到东西了,我看看了网站的结构没变,应该是在动态加载方面变化了,等有时间的时候
看看究竟哪里变了,再把代码优化一下,附上github地址,有兴趣可以参考一下。如果有帮助,给个star把,好不要脸,第一次求star。

https://github.com/Gladysgong/fao

六、后续

后来我又写了一篇文章——用Python下载巨潮资讯农业上市企业的年报PDF文件(二),有兴趣的可以看看。

PhantomJS+Selenium+Scrapy抓取巨潮资讯网企业信息相关推荐

  1. 批量爬取巨潮资讯网中“贵州茅台”相关公告的PDF文件。

    1 需求 批量爬取巨潮资讯网中"贵州茅台"相关公告的PDF文件. 2 代码实现 import reimport requests from selenium import webd ...

  2. python3爬取巨潮资讯网的年报数据

    python3爬取巨潮资讯网的年报数据 前期准备: 需要用到的库: 完整代码: 前期准备: 巨潮资讯网有反爬虫机制,所以先打开巨潮资讯网的年报板块,看看有什么解决办法. 巨潮咨询年报板块 可以通过这样 ...

  3. 基于python+selenium+Chrome自动化爬取巨潮资讯网A股财务报表

    转自同学的博客 引言: 网页爬虫分为静态网页爬虫和动态网页爬虫,前者是指索要获取的网页内容不需要经过js运算或者人工交互, 后者是指获取的内容必须要经过js运算或者人工交互.这里的js运算可能是aja ...

  4. 巧用selenium爬取巨潮资讯公司数据

    巧用selenium爬取巨潮资讯公司数据 立项背景:在做深度学习的过程中利用python进行建模,需要数据来训练模型. 项目目标:通过运用python的selenium模块,爬取巨潮资讯网站关于公司的 ...

  5. selenium爬取巨潮资讯指定领域下所有上市公司的数据并存储到csv文件

    selenium爬取巨潮资讯指定领域下所有上市公司的数据并存储到csv文件 from selenium.webdriver import Chrome #引入selenium中的Chrome from ...

  6. python3爬取巨潮资讯网站年报数据

    python3爬取巨潮资讯网站年报数据 2018年年底巨潮资讯http://www.cninfo.com.cn改版了,之前实习生从网上找的脚本不能用了,因此重新修改了下爬取脚本.最初脚本的原链接忘了, ...

  7. 爬虫|巨潮资讯网上市公司年报爬取

    爬虫|巨潮资讯网上市公司年报爬取 import pandas as pd from selenium import webdriver from selenium.webdriver.common.k ...

  8. python3爬取数据_python3爬取巨潮资讯网站年报数据

    python3爬取巨潮资讯网站年报数据 2018年年底巨潮资讯http://www.cninfo.com.cn改版了,之前实习生从网上找的脚本不能用了,因此重新修改了下爬取脚本.最初脚本的原链接忘了, ...

  9. python 爬虫 requests+BeautifulSoup 爬取巨潮资讯公司概况代码实例

    第一次写一个算是比较完整的爬虫,自我感觉极差啊,代码low,效率差,也没有保存到本地文件或者数据库,强行使用了一波多线程导致数据顺序发生了变化... 贴在这里,引以为戒吧. # -*- coding: ...

  10. 请用Python语言写一个巨潮资讯网批量下载PDF的程序

    下面是一个使用 Python 的简单程序,可以批量下载巨潮资讯网上的 PDF 文件: import requests import os# 巨潮资讯网 PDF 文件的 URL 前缀 url_prefi ...

最新文章

  1. Android内存泄漏简介
  2. pandas的to_csv()使用细节和一些参数
  3. MyEclipse for Mac快捷键
  4. 数据结构练习 00-自测3. 数组元素循环右移问题 (20)
  5. 这一团糟的代码,真的是我写的?!
  6. C++重载下标运算符
  7. javascript设计模式-学习笔记
  8. [转载收藏]三层式开发中的层次划分
  9. Java annotation 自定义注释@interface的用法 转载记录
  10. 音视频即时通讯解决方案
  11. ajax 更新局部视图,使用Ajax局部更新Razor页面的实例代码
  12. 订单超时、定时任务解决方案和思路
  13. 【计算机视觉】不来试试图片轮廓提取?
  14. ASP.NET Core中如何显示[PII is hidden]的隐藏信息
  15. word表格无法跨页断开,内容被隐藏到了页面下方,如何解决?
  16. win系统一键安装redmine+配置+插件安装配置教程【原创-亲测安装成功-一枚测试喵】
  17. sfc /scannow是什么意思,有什么作用?(转载)
  18. 判断一个整数是否为回文数
  19. 微信自动发朋友圈源码
  20. 中华人民共和国刑事诉讼法

热门文章

  1. opencv用shi-Tomasi角点检测实现目标追踪
  2. 小游戏————坦克大战
  3. 大势至USB端口管理软件网络版8.1注册破解
  4. Python的numpy中axis=0、axis=1、axis=2解释
  5. 在word中公式太长,用公式编辑器怎样设置才能自动换行?
  6. noip2017广东提高组复赛成绩
  7. IIS优化,支持10万并发
  8. 合成游戏中的数学原理
  9. 定时关机软件里的锁定计算机,怎么让电脑定时关机设置大全
  10. 相机模型-鱼眼模型/Omnidirectional Camera(1)