一文搞懂如何用Python爬取上市公司資訊
1. 概念準備
- Python基本概念
tb.to_csv(r'1.csv', mode='a', encoding='utf_8_sig', header=1, index=0)
r意思是強制不轉義字串
- 型表格
<table> | 定義表格 |
---|---|
<thead> | 定義表格的頁首 |
<tbody> | 定義表格的主體 |
<tr> | 定義表格的行 |
<th> | 定義表格的表頭 |
<td> | 定義表格單元 |
- 函式
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 | 本地檔案等 |
---|---|
flavor | 解析器 |
header | 標題行 |
skiprows | 跳過的行 |
attrs | 屬性 |
parse_dates | 解析日期 |
- 函式
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='.')
- install/remove of the service denied 管理員許可權
- 啟動:–>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
- 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;
- 常見錯誤
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服務
程式碼是很嚴謹的,如果一個地方檢測確實沒有問題,那就確實不是這裡的問題,而是其他地方,不存在可能之類的傾向。
用於檢測語句塊中的錯誤,從而讓語句捕獲異常資訊並處理。
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")
可以直接理解為“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 | 字串 | %b | 二進位制整數 | %% | % |
---|---|---|---|---|---|
%d | 十進位制整數 | %o | 八進位制整數 |
- 簡介
Navicat是資料庫圖形管理工具,支援MySQL、MariaDB、SQL Server、SQLite、Oracle和PostgreSQL資料庫。Navicat Premium是全系列版本,Navicat for mysql只支援MySQL。
- 選擇器
BeautifulSoup支援 、 、解析器
BeautifulSoup將複雜的HTML文件轉換成一個便於閱讀的樹形結構化檔案,每個節點都是Python物件,共4種:
- Tag
<title>The Dormouse's story</title>
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
類似HTML和XML中的。有兩個屬性name和attributes。
- NavigableString
- BeautifulSoup
- Comment:一個特殊型別的NavigableString物件
具有自動修正程式碼的功能。
result = html.xpath('//li') #獲取所有<li>標籤
- 超文字標記語言
一種建立網頁的標準標記語言;常與和一起使用;標記語言而非程式語言。用來顯示資料,焦點在資料的外觀。而被設計用來傳輸和儲存資料。
是更嚴謹更純淨的版本。
- 擴充套件標記語言
是一種類似於的標記語言,被設計用來結構化(樹結構,具有父兄子元素)、傳輸、儲存資料,焦點在資料的內容,具有自我描述性,而非顯示資料。標籤需要自定義,沒有預定義,是W3C的推薦標準。
僅僅是純文字,文件本身不做任何操作,只是結構化、傳輸、儲存資訊,其傳送、顯示都需要有專門程式。可以理解為,是獨立於軟硬體的傳輸工具。
所有元素必須關閉標籤。標籤區分大小寫。且必須有根元素。
文件中的空格會全部保留。
是首選的樣式語言,而非。
可以擁有屬性,但是屬性值必須加引號。
#特殊符號需要實體引用
<==< >==> &==& &apos==' "=="
#註釋
<!--this is a comment-->
- 在中查詢資訊的語言。
中有七種型別的節點:元素、屬性、文字、名稱空間、處理指令、註釋、文件(根)節點。被當做節點樹來對待。樹的根被稱為文件節點或者根節點。
2. 過程詳解
- 解析
通過刪除#QueryCondition發現不影響開啟網頁,調整pageNum屬性值確定不同頁面,因此確定:
為構造。並注意:
表示A股,換成就是港股,換成就是新三板,因此在網址分頁外再構建一個迴圈就能爬取這三個股市的股票。
- 快速抓取
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',