同花顺上市公司简单数据爬取

针对读者:入门
语言:python
目标:爬取上市公司的股票代码、公司简称、公司全称、创办日期、上市日期、历史年度营收数据、总市值。

结果展示

   { "_id" : { "$oid" : "5c41949eea12859f21423955" },
     "share_id" : "000506",
     "market_value" : "2954276500.000", 
     "revenue" : [ "7.69亿", "8.12亿", "13.88亿", "3.57亿", "9.07亿", "10.71亿", "13.27亿", "11.97亿", "10.07亿", "8.97亿", "6.97亿", "804.36万", "5489.42万", "2.09亿", "3.14亿", "3.71亿", "3.44亿", "2.70亿", "9841.64万", "1.54亿", "2.48亿", "2.09亿", "2.32亿", "2.25亿", "2.38亿", false ], 
     "year" : [ 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009, 2008, 2007, 2006, 2005, 2004, 2003, 2002, 2001, 2000, 1999, 1998, 1997, 1996, 1995, 1994, 1993, 1992 ], 
     "market_time" : "1993-03-12", 
     "start_time" : "1988-05-11", 
     "nick_name" : "中润资源", 
     "name" : "中润资源投资股份有限公司" }

1、在所有公司的入口爬取公司列表,这里可以获取到股票代码以及公司简称。
2、在公司的资料页面,可以获取到公司的全称,里面还有英文名什么的,
3、在公司的财政页面,可以获取到总营收,
4、在一个接口,可以获取到公司的总市值、创办时间、上市时间。
5、将获取到的信息提交到pipeline,并存到MongoDB。

环境准备

1、使用scrapy建立一个项目
2、创建mongo数据库,详细步骤请百度

实现

新建一个爬虫,我这里名为

    name = "share_main"

添加允许的域名

allowed_domains = [
    "q.10jqka.com.cn",
    "stockpage.10jqka.com.cn",
    "basic.10jqka.com.cn",
    "d.10jqka.com.cn"]

定义

  rank_base_page = 'http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/'

parse方法
根据不同的Url对应不同的处理方法
一共有四种页面:
1、所有上市公司的列表页面
2、公司信息详情页
3、公司财务信息页面
4、公司的年营收接口

   def parse(self, response):
    # 获取页面总数
    if "q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page" in response.url:
        max = int(response.xpath("//span[@class='page_info']/text()").extract()[0].split('/')[1])
        print('这是列表页面 一共', max, "页")

        yield from self.handlePage(response)
        for i in range(max):
            if i != 1:
                yield scrapy.Request(rank_base_page + str(i), self.handlePage)

    elif "company.html" in response.url:
        # print("这是company详情页面")
        self.companyParse(response)
    elif "finance.html" in response.url:
        # print("这是finance详情页面")
        self.financeParse(response)
    elif "d.10jqka.com.cn/v2/realhead" in response.url:
        # print("这是realhead详情页面")
        self.infoParse(response)

公司列表页面的的处理方法(handlePage)中获取公司简称以及公司的股票代码,

  • 使用response.xpath("//tr")获取所有的tr标签
    如下图,第一行是“序号 代码 名称”这一行,使用 trs[1:]截取


  • 遍历tr标签,使用tr.xpath(".//a[@target='_blank']")获取tr标签中所有target='_blank'的a标签(.//表示在当前节点中查找所有符合条件的标签)
    text()方法能够获取标签<></>中的文本,这里拿到的就是股票代码与简称
  • 将获取到的股票代码、简称抛出给Pipeline处理
  • 根据获取到的股票代码,生成对应的公司详情、财务详情、以及营收的地址,继续轮询(由于同一个股票代码需要请求三个地址才能够获取全部的信息,所以在请求的时候使用meta加入股票代码,这样处理的时候就知道是哪个股票了)

完整代码如下

 def handlePage(self, response):
    print("处理列表页面")
    trs = response.xpath("//tr")
    for tr in trs[1:]:
        # 股票代码 简称
        a = tr.xpath(".//a[@target='_blank']")

        id = a[0].xpath('text()').extract()[0]
        name = a[1].xpath('text()').extract()[0]
        # print(id, name)

        company = Company()
        company['share_id'] = id
        company['nick_name'] = name
        yield company

        # urls = response.xpath("//tr//a[@target='_blank']/@href").extract()
        # for url in urls:
        #     print(url)
        yield scrapy.Request("http://basic.10jqka.com.cn/" + id + "/company.html", self.companyParse,meta={'share_id': id})
        yield scrapy.Request("http://basic.10jqka.com.cn/" + id + "/finance.html", self.financeParse,meta={'share_id': id})
        yield scrapy.Request("http://d.10jqka.com.cn/v2/realhead/hs_" + id + "/last.js", self.infoParse,meta={'share_id': id})

处理公司详情页面
依旧是使用xpath解析结果,没啥说的

def companyParse(self, response):
    # print('companyParsestart')
    # response.xpath("//div[@stat][@id='detail']//table[@class='m_table']/@class").extract()
    root = response.xpath("//div[@class='content page_event_content']")[0]
    name = root.xpath("//div[@stat][@id='detail']//table[@class='m_table']//tr[1]//td[2]//span/text()")[0].extract()
    start_time = root.xpath("//div[@stat][@id='publish']//table[@class='m_table']//tr[1]//td[1]//span/text()")[
        0].extract()
    market_time = root.xpath("//div[@stat][@id='publish']//table[@class='m_table']//tr[2]//td[1]//span/text()")[
        0].extract()
    print("这是公司详情页 公司全称", name, '成立时间', start_time, '上市时间', market_time)
    company = Company()
    company['share_id'] = response.meta['share_id']
    company['name'] = name
    company['start_time'] = start_time
    company['market_time'] = market_time
    yield company

    # print('cpmpanyParse end')

财务详情页 依然是xpath

def financeParse(self, response):
    # print('financeParse start')
    print("财务详情页 ", "公司ID", response.meta['share_id'], "总营收")
    jsonStr = response.xpath("//p[@id='main']/text()").extract()[0]
    # 按年划分
    finance = json.loads(jsonStr)['year']

    # print(json.dumps(finance[0]))
    # print(json.dumps(finance[6]))
    company = Company()
    company['share_id'] = response.meta['share_id']
    company['year'] = finance[0]
    company['revenue'] = finance[6]
    yield company
    # print('financeParse end')

这里使用的是接口,所以返回的结果需要使用json.loads转化为json结构

def infoParse(self, response):
    # print('infoParse start')
    market_value = json.loads(str(response.body)[41:-2])['items']['3541450']
    print("公司信息接口 ", "公司ID", response.meta['share_id'], "总市值", market_value)
    company = Company()
    company['share_id'] = response.meta['share_id']
    company['market_value'] = market_value
    yield company

    # print('infoParse end')

使用Pipeline处理

pipeline的使用方法参考链接,以股票代码作为唯一值,更新数据库

项目地址
待优化:

  • 扒下来的网页要保存在本地,以便后续使用
  • 使用代理池,实现多线程爬取,优化速度
  • 控制台
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,450评论 1 45
  • 先来看看页面长啥样的:https://book.douban.com/top250 我们将要爬取哪些信息:书名、链...
    Python编程社区阅读 892评论 0 4
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 01 昏黄的灯光下,破旧的牢室里关着一位位精壮的汉子,墙壁上斑驳着干涸的血迹。 这是一家地下格斗场,既然是地下,所...
    泉水里睡着的鹿王阅读 391评论 2 9
  • 今天,我和同学上完课回寝室的路上,在学校的快递站看到了我喜欢的女孩。我兴冲冲地走了过去,打算和她打招呼,那个女孩却...
    DH露露缇雅阅读 185评论 0 0