最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

表格型数据的抓取与存储_中国上市公司数据抓取

XAMPP案例 admin 14浏览 0评论

醉后不知天在水,满船清梦压星河

一.中国上市公司数据抓取

1.1.主函数

from urllib.parse import urlencode
import pandas as pd
import csv
import requests
from bs4 import BeautifulSoup
from requests import RequestException
import mdb  # 导入mongodb数据库
import json
import time

'''
中国上市公司网页数据爬取
将整个爬取分为网页提取、内容解析、数据存储等步骤,依次建立相应的函数
'''
# import lxml
# # 方式一、使用read_html函数将中国上市公司信息快速抓取(抓取少量或次数较少的情况推荐使用)
# for i in range(1, 11):  # 只爬取10页数据
#  url = 'http://s.askci.com/stock/a/?reportTime=2020-03-31&pageNum=%s' % (str(i))
#  tb = pd.read_html(url)[3]  # 经观察发现所需表格是网页中第4个表格,故为[3]
#  tb.to_csv(r'test.csv', mode='a', encoding='utf_8_sig', header=1, index=0)
#  print('第'+str(i)+'页抓取完成')

def get_one_page(i):
 global reportTime
 '''
 网页提取函数,获取html的内容
 :param i: 页码
 :return:  响应的文本内容
 '''
 try:
  # 请求头,模拟浏览器进行网页请求
  headers = {
   'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
  }
  # 传参
  paras = {
   # 可以改报告日期
   'reportTime': reportTime,  # 当前默认时间
   'pageNum': i  # 页码
  }
  # https://s.askci.com/stock/a/0-0?reportTime=2020-03-31&pageNum=1 第一页
  url = 'http://s.askci.com/stock/a/?' + urlencode(paras)
  response = requests.get(url, headers=headers)
  if response.status_code == 200:
   return response.text
  return None
 except RequestException:
  return 'false'

def parse_one_page(html):
 '''
 beautiful soup解析然后提取表格
 :param html:
 :return:
 '''
 soup = BeautifulSoup(html, 'html.parser')
 content = soup.select('#myTable04')[0]  # [0]将返回的list改为bs4类型
 # prettify()优化代码,[0]从pd.read_html返回的list中提取出DataFrame
 tb1 = pd.read_html(content.prettify(), header=0)[0]
 # 修改字段名,便于后续数据库存储
 tb1.rename(columns={'序号': 'serial_number', '股票代码': 'stock_code', '股票简称': 'stock_abbre', '公司名称': 'company_name',
      '省份': 'province', '城市': 'city', '主营业务收入(201712)': 'main_bussiness_income',
      '净利润(201712)': 'net_profit', '员工人数': 'employees', '上市日期': 'listing_date', '招股书': 'zhaogushu',
      '公司财报': 'financial_report', '行业分类': 'industry_classification', '产品类型': 'industry_type',
      '主营业务': 'main_business'}, inplace=True)
 return tb1

# # 方式一.将数据保存至excel文件中
# from openpyxl.workbook import Workbook
# if __name__ == '__main__':
#  begin_time = time.time()
#  df = pd.DataFrame()
#  for i in range(1, 205):
#   html = get_one_page(i)
#   tb = parse_one_page(html)
#   # df = pd.concat([df, tb], axis=0)  # 列头相同,进行上下合并   ignore_index: 忽略之前的索引,重新排序
#   df = df.append(tb)  # 数据在原有的基础上增加
#   print(f'第{i}页抓取完毕')
#   df.to_excel("D:\python\Scripts\crawlerprc04\cdata.xlsx", sheet_name='Sheet1', index=False)
#  end_time = time.time()
#  print(f'数据采集结束,耗时: {end_time-begin_time} s')

# 方式二.将数据存入mongodb数据库
if __name__ == '__main__':
 reportTime = '2019-12-31'  # 报告日期(选取需要的报告时间)
 begin_time = time.time()
 for i in range(1, 205):
  html = get_one_page(i)
  df = parse_one_page(html)
  df['type'] = '上市公司'  # 各类网页数据标识
  df['reportTime'] = reportTime
  mdb.myColl.insert_many(json.loads(df.T.to_json()).values())
  print(f'第{i}页数据添加完成')
 end_time = time.time()
 print(f'数据添加完成,耗时: {end_time-begin_time} s')

1.2.数据库

# -*- coding:utf-8 -*-
from pymongo import MongoClient
# 使用 PyMongo 驱动来连接
myClient = MongoClient("127.0.0.1", port=27017)
# 指定使用的数据库的集合
myColl = myClient.my_test.web

# 查看所有的集合
# collections = myDb.list_collection_names()
# print(collections)

二.中国大学排名数据抓取

2.1.主函数

# -*- coding: utf-8 -*-
'''
中国大学排名网页数据爬取:https://www.shanghairanking.cn/rankings/bcur/2020
将整个爬取分为网页提取、内容解析、数据存储等步骤,依次建立相应的函数
'''
import requests
import bs4
from bs4 import BeautifulSoup
import pandas as pd
import xlwt
import sdb  # 导入sqlserver数据库
from mdb import myColl  # 导入monogdb数据库
import json
import numpy as np

def getHtmlText(url):
    '''
    网页提取
    :param url:访问的url
    :return:获取html返回的内容
    '''
    try:
        rs = requests.get(url, timeout=30)
        rs.raise_for_status()  # 若状态码不是200,引发HttpError异常
        rs.encoding = rs.apparent_encoding  # 修改编码
        return rs.text
    except:
        return 'false'

def fillUnivList(ulist, html):
    '''
    内容解析
    :param ulist: 将获取的内容存放至列表
    :param html:  获取到的html返回的内容
    :return:
    '''
    soup = BeautifulSoup(html, 'html.parser')
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):
            tds = tr('td')
            ulist.append([tds[0].string.strip(), tds[1].a.string.strip(), tds[2].string.strip(), tds[3].string.strip(), tds[4].string.strip(), tds[5].string.strip()])
    # print(ulist)

def printUnivList(ulist, num):
    '''
    打印列表的内容
    :param ulist:
    :param num:
    :return:
    '''
    tplt = "{0:{6}^10}\t{1:{6}^10}\t{2:{6}^10}\t{3:{6}^10}\t{4:{6}^10}\t{5:{6}^10}"  # 占位符
    print(tplt.format("排名", "学校名称", "省市", "类型", "总分", "办学层次", chr(12288)))
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0], u[1], u[2], u[3], u[4], u[5], chr(12288)))

def writeToExcel(ulist):
    '''
    将爬取到的list数据读取至excel文件中
    :param ulist:
    :return:
    '''
    f = xlwt.Workbook()
    sheet1 = f.add_sheet(u'sheet1', cell_overwrite_ok=True)  # 创建sheet
    # 将数据写入第 i 行,第 j 列
    i = 0
    for ul in ulist:
        for j in range(len(ul)):
            sheet1.write(i, j, ul[j])
        i = i + 1
    f.save(r"D:\python\Scripts\crawlerprc04\udata.xls")  # 保存文件
    print('save is finishing')

def writeToSqlserver(ulist):
    '''
    将爬取的list数据读取至sqlserver数据库中
    :param ulist:
    :return:
    '''
    count = 0
    for ul in ulist:
        # print(ul)
        select_sql = "SELECT count(1) FROM C_Univ WHERE name='{0}' ".format(ul[1])
        insert_sql = "INSERT INTO dbo.C_Univ(id, name, areaname, type, tscore, levels)VALUES('{0}','{1}','{2}','{3}','{4}','{5}')".format(ul[0],
                        ul[1], ul[2], ul[3], ul[4], ul[5])
        rs = sdb.findDatas(select_sql)
        # print(rs[0][0])
        if rs[0][0] == 0:  # 当学校名字存在时,数据不进行新增(学校排位id网页数据不唯一)
            sdb.insertDatas(insert_sql)
            count += 1
    print(f'write to sqlserver success, all {count} number')

def writeToMongoDb(ulist):
    '''
    将爬取的list数据转成Json字符串后读取至mongodb数据库中
    :param ulist:
    :return:
    '''
    count = 0
    for li in ulist:
        uname = li[1]
        li.append('中国大学排名')
        list_json = dict(zip(["排名", "学校名称", "省市", "类型", "总分", "办学层次", "type"], li))
        # str_json = json.dumps(list_json, indent=2, ensure_ascii=False)  # json转为string后会报异常,字符串不可修改

        # 数据添加方式一:将集合转换成字典,对数据直接进行插入
        # myColl.insert_one(list_json)

        # 数据添加方式二:当数据库中不存在该学校名称时,进行数据新增,当存在,不进行操作
        myquery = {"学校名称": "{0}".format(uname)}
        Values = {"$setOnInsert": list_json}
        myColl.update_one(myquery, Values, upsert=True)
        count += 1
    print(f'write to mongodb success, all {count} number')

if __name__ == '__main__':
    uinfo = []
    url = 'https://www.shanghairanking.cn/rankings/bcur/2020'
    html = getHtmlText(url)
    fillUnivList(uinfo, html)
    # printUnivList(ulist, 500)  # 将排名前500的大学进行打印输出
    # writeToExcel(uinfo)  # 将爬取的list类型数据存放至excel中
    # writeToSqlserver(uinfo)  # 将爬取的list类型数据存放至sqlserver数据库中
    writeToMongoDb(uinfo)  # 将爬取的list类型数据存放至mongodb数据库

2.2.数据库

# -*- coding: utf-8 -*-
import pymssql
import pandas

server = '127.0.0.1'
user = 'fqj03'
password = '1'
database = 'myweb'
charset = 'utf-8'

conn = pymssql.connect(server, user, password, database, charset)
# 使用 cursor() 方法创建一个游标对象
cur = conn.cursor()

def findDatas(sql):
    '''
    数据的查询
    :param sql:
    :return:
    '''
    # 执行SQL语句
    cur.execute(sql)
    # 获取所有记录列表
    results = cur.fetchall()
    return results
    # 关闭数据库连接
    conn.close()

def insertDatas(sql):
    '''
    数据的增删改
    :param sql:
    :return:
    '''
    try:
       # 执行SQL语句
       cur.execute(sql)
       conn.commit()
       return True
    except:
       return False
    # 关闭数据库连接
    conn.close()

三.阅读指南

3.1.利用pandas库中的read_html方法快速抓取网页中常见的表格型数据

table类型的表格网页结构大致如下:
<table id="...">   # <table>:定义表格
    <thead>                    # <thead>:定义表格的页眉
    <tr>
    <th>...</th>               # <th>:定义表格的表头
    </tr>                      # <tr>:定义表格的行
    </thead>
    <tbody>                    # <toody>:定义表格的主题
        <tr>
            <td>...</td>       # <td>:定义表格单元
        </tr>
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
        ...
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
    </tbody>
</table>
这样的表格数据,就可以利用pandas模块里的read_html函数方便快捷地抓取下来
(并不是所有的表格数据都可以使用类似方法进行数据爬取,有些网站中的表格,
html中前面不是table格式,而是list格式,这种表格则不适用read_html进行爬取,
得用其它的方法,比如selenium)

3.2.中国上市公司分析

3.2.1.中国上市公司网页的url分析(只有pageNum随着页数发生改变,报告时间可以自行修改)
https://s.askci.com/stock/a/0-0?reportTime=2020-03-31&pageNum=1  # 第一页
https://s.askci.com/stock/a/0-0?reportTime=2020-03-31&pageNum=2  # 第二页
https://s.askci.com/stock/a/0-0?reportTime=2020-03-31&pageNum=n  # 第n页

再注意其它参数:
a:表示A股,把a替换为h,表示港股;
把a替换为xsb,则表示新三板。
那么,在网址分页for循环外部再加一个for循环,就可以爬取这三个股市的股票了。

3.2.2.read_html函数的api:
pandas.read_html(io, match='.+', flavor=None, header=None, index_col=None, skiprows=None, attrs=None, parse_dates=False,
tupleize_cols=None, thousands=', ', encoding=None, decimal='.', converters=None, na_values=None, keep_default_na=True,
displayed_only=True)

常用的参数:
io:可以是url、html文本、本地文件等;
flavor:解析器;
header:标题行;
skiprows:跳过的行;
attrs:属性,比如 attrs = {'id': 'table'};
parse_dates:解析日期

注意:返回的结果是**DataFrame**组成的**list**。

3.2.3.将整个爬取分为网页提取、内容解析、数据存储等步骤,依次建立相应的函数
网页提取: response = requests.get(url, headers=headers)  提取网页中的文本内容
内容解析: beautiful soup解析然后提取表格
df = pd.read_html(content.prettify(), header=0)[0]  将提取的网页内容进行解析成dataframe格式数据

3.2.4.将df格式数据添加自己想添加的额外字段后并将数据写入excel文件或数据库中
将数据写入excel文件:
df.to_excel("D:\python\Scripts\crawlerprc04\cdata.xlsx", sheet_name='Sheet1', index=False)  # index:不含行索引

将数据写入mongodb数据库中:
mdb.myColl:指定的数据库对应的集合(表)
将数据转置的dataframe对象序列化成json对象,再反序列化成字典存放进mongodb中
mdb.myColl.insert_many(json.loads(df.T.to_json()).values())

3.3.中国大学排名分析

3.3.1.中国大学排名网页数据爬取:https://www.shanghairanking.cn/rankings/bcur/2020
将整个爬取分为网页提取、内容解析、数据存储等步骤,依次建立相应的函数

3.3.2.Beautiful Soup库基础知识  https://blog.csdn.net/i_chaoren/article/details/63282877
    2.1.Beautiful Soup库的理解
    Beautiful Soup库是解析、遍历、维护"标签树"的功能库
    <html>  # 标签树
        <body>
            <p>...</p>
        </body>
    </html>
    # p : 名称  .name
    #  : 属性  .attrs
    # ... 非属性字符串/注释  .string

3.3.3.将集合型数据转换成字典类型数据
    3.1.zip函数:接受任意多个序列作为参数,返回一个tuple列表
    3.2.dict:字典的转换
    3.3.dict(zip(["排名", "学校名称", "省市", "类型", "总分", "办学层次", "type"], list))

3.3.4.mongodb数据库的数据新增
    4.1.只新增
        db.mycollection.insert_one(json)
    4.2.当数据不存在进行新增,存在不做操作或者进行更新($setOnInsert)

dz08python

dz008python

转载请注明:XAMPP中文组官网 » 表格型数据的抓取与存储_中国上市公司数据抓取