1. 前言 首先自我介紹一下,我是一個做 Java 的開發人員,從今年下半年開始,一直在各大技術博客網站發表自己的一些技術文章,差不多有幾個月了,之前在 cnblog 博客園加了網站統計代碼,看到每天的訪問量逐漸多了起來,國慶正好事情不多,就想著寫一個爬蟲,看下具體閱讀量增加了多少,這也就成了本文的 ...
1. 前言
首先自我介紹一下,我是一個做 Java 的開發人員,從今年下半年開始,一直在各大技術博客網站發表自己的一些技術文章,差不多有幾個月了,之前在 cnblog 博客園加了網站統計代碼,看到每天的訪問量逐漸多了起來,國慶正好事情不多,就想著寫一個爬蟲,看下具體閱讀量增加了多少,這也就成了本文的由來。
這裡註意:不管你是為了Python就業還是興趣愛好,記住:項目開發經驗永遠是核心,如果你缺新項目練習或者沒有python精講教程,可以去小編的Python交流.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,裡面很多新python教程項目,還可以跟老司機交流討教!
2. 技術選型
爬蟲這個功能,我個人理解是什麼語言都能寫的,只要能正常發送 HTTP 請求,將響應回來的靜態頁面模版 HTML 上把我們所需要的數據提取出來就可以了,原理很簡單,這個東西當然可以手動去統計收集,但是網路平臺畢竟還是很多的,還是畫點時間,寫個爬蟲把數據爬取下來,存到資料庫里,然後寫一個統計報表的 SQL 語句比較方便,後續如果有時間的話,我會寫一個簡單的前後端分離的報表樣例分享出來。
網上現在 Python 爬蟲的課程非常的火爆,其實我心裡也有點小九九,想玩點騷操作,不想用老本行去寫這個爬蟲,當然最後的事實是證明確實用 Python 寫爬蟲要比用 Java 來寫爬蟲要簡單的多。
3. 環境準備
首先筆者的電腦是 Win10 的,Python 選用的是 3.7.4 ,貌似現在網上 Python3 的爬蟲教程並不多,其中還是遇到不少的問題,下麵也會分享給大家。
開發工具筆者選用的是 VSCode ,在這裡推薦一下微軟這個開源的產品,非常的輕量化,需要什麼插件自己安裝就好,不用的插件一律不要,自主性非常高,如果感覺搞不定的朋友可以選擇 JetBrains 提供的 Pycharm ,分為社區版和付費版,一般而言,我們使用社區版足矣。
筆者這裡直接新建了一個文件夾,創建了一個名為 spider-demo.py
的文件,這個就是我們一會要寫的爬蟲的文件了,可以給大家看下筆者的開發環境,如下:
這其實是一個調試成功的截圖,從下麵列印的日誌中可以看到,筆者這裡抓取了三個平臺的數據。
4. 資料庫
筆者使用的數據是 Mysql 5.7.19 版本,資料庫的字元集是使用的 utf8mb4 ,至於為什麼使用 utf8mb4 而不是 utf8 ,各位百度一下吧,很多人講的都比我講的好,我簡單說一句就是 Mysql 的 utf8 其實是一個假的 utf8 ,而後面增加的字元集 utf8mb4 才是真正的 utf8 。
而 Python 連接 Mysql 也是需要驅動的,和在 Java 中連接資料庫需要驅動一樣,這裡使用的是 pymysql ,安裝命令:
pip install pymysql
複製代碼
有沒有感覺很簡單, pip 是 Python 的一個包管理工具,我的個人理解是類似於一個 Maven 的東西,所有的我們需要的第三方的包都能在這個上面下載到。
當然,這裡可能會出現 timeout
的情況,視大家的網路情況而定,我在晚上執行這個命令的時候真的是各種 timeout
,當然 Maven 會有國內的鏡像戰, pip 顯然肯定也會有麽,這裡都列給大家:
- 阿裡雲 mirrors.aliyun.com/pypi/simple…
- 中國科技大學 pypi.mirrors.ustc.edu.cn/simple/
- 豆瓣(douban) pypi.douban.com/simple/
- 清華大學 pypi.tuna.tsinghua.edu.cn/simple/
- 中國科學技術大學 pypi.mirrors.ustc.edu.cn/simple/
具體使用方式命令如下:
pip install -i https://mirrors.aliyun.com/pypi/simple/ 庫名
複製代碼
筆者這裡僅僅嘗試過阿裡雲和清華大學的鏡像站,其餘未做嘗試,以上內容來自於網路。
表結構,設計如下圖,這裡設計很粗糙的,簡簡單單的只做了一張表,多餘話我也不說,大家看圖吧,欄位後面都有註釋了:
建表語句提交至 Github 倉庫,有需要的同學可以去查看。
5. 實戰
整體思路分以下這麼幾步:
- 通過 GET 請求將整個頁面的 HTML 靜態資源請求回來
- 通過一些匹配規則匹配到我們需要的數據
- 存入資料庫
5.1 請求 HTML 靜態資源
Python3 為我們提供了 urllib 這個標準庫,無需我們額外的安裝,使用的時候需要先引入:
from urllib import request
複製代碼
接下來我們使用 urllib 發送 GET 請求,如下:
req_csdn = request.Request('https://blog.csdn.net/meteor_93')
req_csdn.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36')
html_csdn = request.urlopen(req_csdn).read().decode('utf-8')
複製代碼
User Agent中文名為用戶代理,簡稱 UA,它是一個特殊字元串頭,使得伺服器能夠識別客戶使用的操作系統及版本、CPU 類型、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語言、瀏覽器插件等。
這裡在請求頭中添加這個是為了模擬瀏覽器正常請求,很多伺服器都會做檢測,發現不是正常瀏覽器的請求會直接拒絕,雖然後面實測筆者爬取的這幾個平臺都沒有這項檢測,但是能加就加一下麽,當然真實的瀏覽器發送的請求頭裡面不僅僅只有一個 UA ,還會有一些其他的信息,如下圖:
筆者這裡的 UA 信息是直接從這裡 Copy 出來的。代碼寫到這裡,我們已經拿到了頁面靜態資源 html_csdn
,接下來我們就是要解析這個資源,從中匹配出來我們需要的信息。
5.2 xpath 數據匹配
xpath 是什麼?
XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。 XPath 是 W3C XSLT 標準的主要元素,並且 XQuery 和 XPointer 都構建於 XPath 表達之上。
從上面這句話我們可以看出來, xpath 是用來查找 XML ,而我們的 HTML 可以認為是語法不標準的 XML 文檔,恰巧我們可以通過這種方式來解析 HTML 文檔。
我們在使用 xpath 之前,需要先安裝 xpath 的依賴庫,這個庫並不是 Python 提供的標準庫,安裝語句如下:
pip install lxml
複製代碼
如果網路不給力的同學可以使用上面的鏡像站進行安裝。
而 xpath 的表達式非常簡單,具體的語法大家可以參考 W3school 提供的教程(www.w3school.com.cn/xpath/xpath… ),筆者這裡不多介紹,具體使用方式如下:
read_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[3]/dl[2]/dd/@title')[0]
fans_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="fan"]/text()')[0]
rank_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[3]/dl[4]/@title')[0]
like_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[2]/dl[3]/dd/span/text()')[0]
複製代碼
這裡筆者主要獲取了總閱讀數、總粉絲數、排名和總點贊數。
這裡列舉幾個最基礎的使用,這幾個使用在本示例中已經完全夠用:
表達式 | 描述 |
---|---|
nodename |
選取此節點的所有子節點。 |
/ |
從根節點選取。 |
// |
從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。 |
. |
選取當前節點。 |
.. |
選取當前節點的父節點。 |
@ |
選取屬性。 |
text |
選取當前節點內容。 |
還有一種簡單的方式,我們可以通過 Chrome 瀏覽器獲取 xpath 表達式,具體操作見截圖:
打開 F12 ,滑鼠右鍵需要生成 xpath 表達式的內容,點擊 Copy -> Copy XPath 即可。
這裡有一點需要註意,我們直接通過 xpath 取出來的數據數據類型並不是基礎數據類型,如果要做運算或者字元串拼接,需要做類型強轉,否則會報錯,如下:
req_cnblog = request.Request('https://www.cnblogs.com/babycomeon/default.html?page=2')
req_cnblog.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36')
html_cnblog = request.urlopen(req_cnblog).read().decode('utf-8')
max_page_num = etree.HTML(html_cnblog).xpath('//*[@id="homepage_top_pager"]/div/text()')
# 最大頁數
max_page_num = re.findall(r"\d+\.?\d*", str(max_page_num))[0]
複製代碼
這裡需要獲取 cnblog 的博客最大頁數,首先取到了 max_page_num
,這裡直接做 print
的話是可以正常列印一個字元串出來的,但是如果直接去做正則匹配,就會類型錯誤。
5.3 寫入資料庫
資料庫的操作我就不多做介紹了,有寫過 Java 的同學應該都很清楚 jdbc 是怎麼寫的,先使用 ip 、 port 、 用戶名、密碼、資料庫名稱、字元集等信息獲取連接,然後開啟連接,寫一句 sql ,把 sql 拼好,執行 sql ,然後提交數據,然後關閉連接,代碼如下:
def connect():
conn = pymysql.connect(host='localhost',
port=3306,
user='root',
password='123456',
database='test',
charset='utf8mb4')
# 獲取操作游標
cursor = conn.cursor()
return {"conn": conn, "cursor": cursor}
connection = connect()
conn, cursor = connection['conn'], connection['cursor']
sql_insert = "insert into spider_data(id, plantform, read_num, fans_num, rank_num, like_num, create_date) values (UUID(), %(plantform)s, %(read_num)s, %(fans_num)s, %(rank_num)s, %(like_num)s, now())"
複製代碼
在本示例中,爬蟲只負責一個數據爬取工作,所以只需要一句 insert 語句就夠了,然後在每個平臺爬取完成後,將這句 sql 中的占位符替換掉,執行 sql 後 commit 操作即可,示例代碼如下:
csdn_data = {
"plantform": 'csdn',
"read_num": read_num_csdn,
"fans_num": fans_num_csdn,
"rank_num": rank_num_csdn,
"like_num": like_num_csdn
}
cursor.execute(sql_insert, csdn_data)
conn.commit()
複製代碼
6. 小結
經過這麼一次 Python 爬蟲的實際體驗後,確實感覺使用 Python 寫程式語法非常的簡單,整體程式使用 130+ 行,大致估算一下,如果使用 Java 書寫同樣的功能,可能會需要 200+ 行,使用 httpClient 發送 GET 請求再解析響應就不是這麼 Python 這種簡簡單單的 2~3 行代碼搞的定的。本示例的爬蟲其實還非常的不完善,目前只能爬取不需要登錄的平臺的數據,有的平臺需要登錄後才能看到統計數據,這就要和 Cookies 相結合才能完成模擬登陸的過程。後續有空我會接著完善這隻小爬蟲的。
最後註意:不管你是為了Python就業還是興趣愛好,記住:項目開發經驗永遠是核心,如果你缺新項目練習或者沒有python精講教程,可以去小編的Python交流.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,裡面很多新python教程項目,還可以跟老司機交流討教!
本文的文字及圖片來源於網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。
。