5 行程式碼就能入門爬蟲?

第2大腦發表於2019-01-11

摘要:5 行程式碼就能寫一個 Python 爬蟲,文底公佈抽獎送書活動的中獎名單。

如果你是比較早關注我的話,會發現我此前的大部分文章都是在寫 Python 爬蟲,前後大概寫了十幾個爬蟲實戰案例,一直在埋頭往前寫,但卻沒有回到原點過,沒有寫過為什麼要爬蟲、爬蟲難不難、怎麼入門爬蟲這些問題。另外,我覺得關注我的朋友中有不少是剛剛入門 Python 或者想學習 Python 的,為了更加友好一些,所以也有必要說一說這幾個問題。基於這兩點思考,今天就來談談 如何用快速入門爬蟲

先說結論:入門爬蟲很容易,幾行程式碼就可以,可以說是學習 Python 最簡單的途徑

以我純小白、零基礎的背景來說,入門爬蟲其實很容易,容易在程式碼編寫很簡單,簡單的爬蟲通常幾行就能搞定,而不容易在確定爬蟲的目標,也就是說為什麼要去寫爬蟲,有沒有必要用到爬蟲,是不是手動操作幾乎無法完成,網際網路上有數以百萬千萬計的網站,到底以哪一個網站作為入門首選,這些問題才是難點。所以在動手寫爬蟲前,最好花一些時間想一想這清楚這些問題。

Talk is cheap. Show me the code」,下面我就以曾寫過的一個爬蟲為例,說一說我是如何快速入門 Python 爬蟲的。

▌確立目標

第一步,確立目標。

為什麼當時想起寫這個爬蟲呢,是因為這是曾經在工作中想要解決的問題,當時不會爬蟲,只能用 Excel 花了數個小時才勉強地把資料爬了下來, 所以在接觸到爬蟲後,第一個想法就是去實現曾未實現的目標。以這樣的方式入門爬蟲,好處顯而易見,就是有了很明確的動力。
很多人學爬蟲都是去爬網上教程中的那些網站,網站一樣就算了,爬取的方法也一模一樣,等於抄一遍,不是說這樣無益,但是會容易導致動力不足,因為你沒有帶著目標去爬,只是為了學爬蟲而爬,爬蟲雖然是門技術活,但是如果能 建立在興趣愛好或者工作任務的前提下,學習的動力就會強很多。

在確定好爬蟲目標後,接著我就在腦中預想了想要得到什麼樣的結果、如何展示出來、以什麼形式展現這些問題。所以,我在爬取網站之前,就預先構想出了想要的一個結果,大致是下面這張圖的樣子。

5 行程式碼就能入門爬蟲?

目標是利用爬下來的資料,嘗試從不同維度年份、省份、城市去分析全國的股市資訊,然後透過視覺化圖表呈現出來。

拋開資料,可能你會覺得這張圖在排版佈局、色彩搭配、字型文字等方面還挺好看的。這些呢,就跟爬蟲沒什麼關係了,而跟審美有關,提升審美的一種方式是可以透過做 PPT 來實現:

∞ 國外最牛逼的一套 PPT 作品分享給你

所以你看,我們們說著說著就從爬蟲跳到了 PPT,不得不說我此前發的文章鋪墊地很好啊,哈哈。其實,在職場中,你擁有的技能越多越好。

▌直接開始

確定了目標後,第二步就可以開始寫爬蟲了,如果你像我一樣,之前沒有任何程式設計基礎,那我下面說的思路,可能會有用。

剛開始動手寫爬蟲,我只關注最核心的部分,也就是先成功抓到資料,其他的諸如:下載速度、儲存方式、程式碼條理性等先不管,這樣的程式碼簡短易懂、容易上手,能夠增強信心。

所以,我在寫第一遍的時候,只用了 5 行程式碼,就成功抓取了全部所需的資訊,當時的感覺就是很爽,覺得爬蟲不過如此啊,自信心爆棚。

1import pandas as pd
2import csv
3for i in range(1,178):  # 爬取全部頁
4    tb = pd.read_html('%s' % (str(i)))[3
5    tb.to_csv(r'1.csv', mode='a', encoding='utf_8_sig', header=1, index=0)

3000+ 上市公司的資訊,安安靜靜地躺在 Excel 中:

5 行程式碼就能入門爬蟲?

▌不斷完善

有了上面的信心後,我開始繼續完善程式碼,因為 5 行程式碼太單薄,功能也太簡單,大致從以下幾個方面進行了完善:

  • 增加異常處理

由於爬取上百頁的網頁,中途很可能由於各種問題導致爬取失敗,所以增加了 try except 、if 等語句,來處理可能出現的異常,讓程式碼更健壯。

  • 增加程式碼靈活性

初版程式碼由於固定了 URL 引數,所以只能爬取固定的內容,但是人的想法是多變的,一會兒想爬這個一會兒可能又需要那個,所以可以透過修改 URL 請求引數,來增加程式碼靈活性,從而爬取更靈活的資料。

  • 修改儲存方式

初版程式碼我選擇了儲存到 Excel 這種最為熟悉簡單的方式,人是一種惰性動物,很難離開自己的舒適區。但是為了學習新知識,所以我選擇將資料儲存到 MySQL 中,以便練習 MySQL 的使用。

  • 加快爬取速度

初版程式碼使用了最簡單的單程式爬取方式,爬取速度比較慢,考慮到網頁數量比較大,所以修改為了多程式的爬取方式。

經過以上這幾點的完善,程式碼量從原先的 5 行增加到了下面的幾十行:

 1import requests
2import pandas as pd
3from bs4 import BeautifulSoup
4from lxml import etree
5import time
6import pymysql
7from sqlalchemy import create_engine
8from urllib.parse import urlencode  # 編碼 URL 字串
9
10start_time = time.time()  #計算程式執行時間
11def get_one_page(i):
12    try:
13        headers = {
14            'User-Agent''Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
15        }
16        paras = {
17        'reportTime''2017-12-31',
18        #可以改報告日期,比如2018-6-30獲得的就是該季度的資訊
19        'pageNum': i   #頁碼
20        }
21        url = ' + urlencode(paras)
22        response = requests.get(url,headers = headers)
23        if response.status_code == 200:
24            return response.text
25        return None
26    except RequestException:
27        print('爬取失敗')
28
29def parse_one_page(html):
30    soup = BeautifulSoup(html,'lxml')
31    content = soup.select('#myTable04')[0#[0]將返回的list改為bs4型別
32    tbl = pd.read_html(content.prettify(),header = 0)[0]
33    # prettify()最佳化程式碼,[0]從pd.read_html返回的list中提取出DataFrame
34    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)
35    return tbl
36
37def generate_mysql():
38    conn = pymysql.connect(
39        host='localhost',
40        user='root',
41        password='******',
42        port=3306,
43        charset = 'utf8',  
44        db = 'wade')
45    cursor = conn.cursor()
46
47    sql = 'CREATE TABLE IF NOT EXISTS listed_company (serial_number INT(20) NOT NULL,stock_code INT(20) ,stock_abbre VARCHAR(20) ,company_name VARCHAR(20) ,province VARCHAR(20) ,city VARCHAR(20) ,main_bussiness_income VARCHAR(20) ,net_profit VARCHAR(20) ,employees INT(20) ,listing_date DATETIME(0) ,zhaogushu VARCHAR(20) ,financial_report VARCHAR(20) , industry_classification VARCHAR(20) ,industry_type VARCHAR(100) ,main_business VARCHAR(200) ,PRIMARY KEY (serial_number))'
48    cursor.execute(sql)
49    conn.close()
50
51def write_to_sql(tbl, db = 'wade'):
52    engine = create_engine('mysql+pymysql://root:******@localhost:3306/{0}?charset=utf8'.format(db))
53    try:
54        tbl.to_sql('listed_company2',con = engine,if_exists='append',index=False)
55        # append表示在原有表基礎上增加,但該表要有表頭
56    except Exception as e:
57        print(e)
58
59def main(page):
60    generate_mysql()
61    for i in range(1,page):  
62        html = get_one_page(i)
63        tbl = parse_one_page(html)
64        write_to_sql(tbl)
65
66# # 單程式
67if __name__ == '__main__':    
68    main(178)
69    endtime = time.time()-start_time
70    print('程式執行了%.2f秒' %endtime)
71
72# 多程式
73from multiprocessing import Pool
74if __name__ == '__main__':
75     pool = Pool(4)
76     pool.map(main, [i for i in range(1,178)])  #共有178頁
77    endtime = time.time()-start_time
78    print('程式執行了%.2f秒' %(time.time()-start_time))

雖然程式碼行數增加了不少,但是這個過程卻覺得很自然,因為每次修改都是針對一個小點,一點點去學,搞懂後新增進來,而如果讓我上來就直接寫出這幾十行的程式碼,我很可能就放棄了。

所以,你可以看到,入門爬蟲是有套路的,最重要的是給自己信心。

以上,我從一個小點結合一個例項,介紹了入門學習爬蟲的方法,希望對你有用。當然還有其他點,之後再說。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900353/viewspace-2375539/,如需轉載,請註明出處,否則將追究法律責任。

相關文章