1. 程式人生 > >一文搞懂如何用Python爬取上市公司資訊

一文搞懂如何用Python爬取上市公司資訊

1. 概念準備

  • Python基本概念
tb.to_csv(r'1.csv', mode='a', encoding='utf_8_sig', header=1, index=0)

r意思是強制不轉義字串

  • TableTable型表格
<table> 定義表格
<thead> 定義表格的頁首
<tbody> 定義表格的主體
<tr> 定義表格的行
<th> 定義表格的表頭
<td> 定義表格單元
  • DataFrame.read_htmlDataFrame.read\_html
    函式
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 urlurl htmlhtml 本地檔案等
flavor 解析器
header 標題行
skiprows 跳過的行
attrs 屬性
parse_dates 解析日期
  • pandas.Data.to_csv()pandas.Data.to\_csv()函式

官方文件 示例講解 中英文釋

DataFrame.to_csv(path_or_buf=None, sep=', ', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=
None, mode='w', encoding=None, compression=None, quoting=None, quotechar='"', line_terminator='\n', chunksize=None, tupleize_cols=None, date_format=None, doublequote=True, escapechar=None, decimal='.')

初級教程

  1. install/remove of the service denied 管理員許可權
  2. 啟動:–>G: -->cd G:\MySQL\mysql-8.0.13-winx64\bin -->mysql -u root -p -->123456

建立資料庫–>create database db_name;

檢視已有資料庫–>show databases;

選擇資料庫–>use db_name;

刪除資料庫–>drop databse db_name;

當前資料庫下所有表的名字–>show tables; 或者–>show tables from db_name;

查看錶結構–>desc tb_name; -->describe tb_name; -->show columns from tb_name; —>show create table tb_name

  1. user與授權

*.* 指所有資料庫,%指所有ip地址

查詢mysql的user表–>select user,host from mysql.user;

建立使用者–>CREATE USER ‘user_name’@‘host_address’ IDENTIFIED BY ‘password’; –> insert into mysql.user(Host,User,Password)values(“localhost”,“name”,password(“12”));

刪除使用者–>delete from user where user=‘user_name’ and host=‘localhost’ ; -->flush privileges; —>drop user ‘user_name’@‘host’;

賦予使用者所有許可權–>create user ‘root’@’%’ identified by ‘root’; --------------------------->grant all provoleges on . to ‘root’@’%’ with grant option;

取消使用者所有許可權–>REVOKE privilege ON databasename.tablename FROM ‘username’@‘host’;

更改密碼,其他方法都不行.–>ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘你的密碼’;

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
flush privileges;
#上面是以前版本的語法,下面才是MySQL8.0的語法
CREATE USER 'root'@'%' IDENTIFIED BY 'root';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
  1. 常見錯誤

net start mysql 發生系統錯誤2。mysqld需要安裝在bin目錄下,先刪除之前的服務mysqld --remove,然後在bin下重新安裝mysqld install。

net stop mysql 發生系統錯誤 5。訪問許可權問題,切換到管理員許可權。

ERROR 1049, "Unknown database ‘wade’。無法連線到資料庫,檢查連線設定。

ERROR 1064,語法問題。MySQL版本升級後很多語法都變換了格式。

(pymysql.err.OperationalError) (1045, “Access denied for user ‘root’@‘localhost’ (using password: YES)”) 通過pymysql儲存資料到MySQL中出現。1.常規資料只能解決密碼錯誤,但是我這裡密碼沒有問題(結果只是這裡,但不是關注的那段程式碼,而是另外的地方用到了)。2.phpwamp軟體自身有mysql服務,可能會佔用mysql的埠(只能開一個),開啟服務,刪掉多餘的。3.資料庫許可權問題,未給root使用者分配所有許可權,本地客戶端無權登入root使用者。給root使用者賦許可權時,注意語法問題。三種方法都沒有解決問題。

ERROR 2003: Can’t connect to MySQL server on ‘localhost’ (10061)。MySQL服務關閉了。在管理員許可權下開啟cmd–>net start mysql 或者–>cmd–>services.msc–>手動開啟MySQL服務

程式碼是很嚴謹的,如果一個地方檢測確實沒有問題,那就確實不是這裡的問題,而是其他地方,不存在可能之類的傾向。

用於檢測trytry語句塊中的錯誤,從而讓exceptexcept語句捕獲異常資訊並處理。

try:
     Normal execution block
except A:
     Exception A handle
except B:
     Exception B handle
except:
     Other exception handle
else:
     if no exception,get here
finally:
     print("finally")   

exceptexcept可以直接理解為“if…成立並執行。

一個小遊戲,讓使用者猜數字,提示“大了”“小了”,直到使用者猜對。(程式碼可完美執行)

from random import randint
 
target = randint(0,100)
while 1:
    guess = input('plz guess a interger between 0 and 100:')
    try:
        num = int(guess)
    except:
        print('plz input an INTERGER!!')
    else:
        break
time = 1
while num != target:
    if num < target:
        print('smaller')
    elif num > target:
        print('bigger')
    while 1:
        guess = input('guess again...')
        try:
            num = int(guess)
        except:
            print('plz input an INTERGER!!')
        else:
            break
    time = time + 1
else:
    print('you win...you get the number in ',time,' steps!!')
  • URL中特殊符號意義

%s 格式化字串(示例1 示例2)

%s 字串 %b 二進位制整數 %% %
%d 十進位制整數 %o 八進位制整數
  • NavicatNavicat簡介

官方文件

Navicat是資料庫圖形管理工具,支援MySQL、MariaDB、SQL Server、SQLite、Oracle和PostgreSQL資料庫。Navicat Premium是全系列版本,Navicat for mysql只支援MySQL。

  • BeautifulSoupBeautifulSoup選擇器

BeautifulSoup支援HTMLHTMLlxmllxmlHtml5libHtml5lib解析器

BeautifulSoup將複雜的HTML文件轉換成一個便於閱讀的樹形結構化檔案,每個節點都是Python物件,共4種:

  1. Tag
<title>The Dormouse's story</title>
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

類似HTML和XML中的tagtag。有兩個屬性name和attributes。

  1. NavigableString
  2. BeautifulSoup
  3. Comment:一個特殊型別的NavigableString物件

具有自動修正HTMLHTML程式碼的功能。

result = html.xpath('//li') #獲取所有<li>標籤
  • HTML(HyperTextMarkupLanguage)HTML(HyperTextMarkupLanguage)超文字標記語言

一種建立網頁的標準標記語言;常與CSSCSSJavaScriptJavaScript一起使用;標記語言而非程式語言。用來顯示資料,焦點在資料的外觀。而XMLXML被設計用來傳輸和儲存資料。

XHTMLXHTML是更嚴謹更純淨的HTMLHTML版本。

  • XML(ExtensibleMarkupLanguage)XML(ExtensibleMarkupLanguage) 擴充套件標記語言

是一種類似於HTMLHTML的標記語言,被設計用來結構化(樹結構,具有父兄子元素)、傳輸、儲存資料,焦點在資料的內容,具有自我描述性,而非顯示資料。標籤需要自定義,沒有預定義,是W3C的推薦標準。

XMLXML僅僅是純文字,文件本身不做任何操作,只是結構化、傳輸、儲存資訊,其傳送、顯示都需要有專門程式。可以理解為,XMLXML是獨立於軟硬體的傳輸工具。

所有元素必須關閉標籤。標籤區分大小寫。且必須有根元素。

文件中的空格會全部保留。

XSLTXSLT是首選的XMLXML樣式語言,而非CSSCSS

可以擁有屬性,但是屬性值必須加引號。

#特殊符號需要實體引用
&lt==<   &gt==>   &amp==&   &apos=='   &quot=="
#註釋
<!--this is a comment-->
  • XPathXPathXMLXML中查詢資訊的語言。

XPathXPath中有七種型別的節點:元素、屬性、文字、名稱空間、處理指令、註釋、文件(根)節點。XMLXML被當做節點樹來對待。樹的根被稱為文件節點或者根節點。

2. 過程詳解

  • URLURL解析

通過刪除#QueryCondition發現不影響開啟網頁,調整pageNum屬性值確定不同頁面,因此確定:

為構造urlurl。並注意:

aa表示A股,aa換成hh就是港股,aa換成xsbxsb就是新三板,因此在網址分頁forfor外再構建一個forfor迴圈就能爬取這三個股市的股票。

  • 快速抓取
import pandas as pd
import csv

for i in range(1,178):  # 爬取全部177頁資料
    url = 'http://s.askci.com/stock/a/?reportTime=2017-12-31&pageNum=%s' % (str(i))
    tb = pd.read_html(url)[3] #經觀察發現所需表格是網頁中第4個表格,故為[3]
    tb.to_csv(r'1.csv', mode='a', encoding='utf_8_sig', header=1, index=0)
    print('第'+str(i)+'頁抓取完成')
  • 網頁提取函式
def get_one_page(i):
    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': '2017-12-31',   
        #可以改報告日期,比如2018-6-30獲得的就是該季度的資訊
        'pageNum': i   #頁碼
        }
        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:
        print('爬取失敗')
  • 內容解析函式
def parse_one_page(html):
    soup = BeautifulSoup(html,'lxml')
    content = soup.select('#myTable04')[0] #[0]將返回的list改為bs4型別
    tbl = pd.read_html(content.prettify(),header = 0)[0]
    # prettify()優化程式碼,[0]從pd.read_html返回的list中提取出DataFrame

    tbl.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)

    print(tbl)
    # return tbl
    # rename將表格15列的中文名改為英文名,便於儲存到mysql及後期進行資料分析
    # tbl = pd.DataFrame(tbl,dtype = 'object') #dtype可統一修改列格式為文字
  • 主函式
# 主函式
def main(page):
    for i in range(1,page):   # page表示提取頁數
        html = get_one_page(i)
        parse_one_page(html)

# 單程序
if __name__ == '__main__':    
    main(178)   #共提取n頁
  • 建立在資料庫中存放資料的表格
import pymysql

def generate_mysql():
    conn = pymysql.connect(
        host='localhost',   # 本地伺服器
        user='root',
        password='******',  # 你的資料庫密碼
        port=3306,          # 預設埠
        charset = 'utf8',