爬蟲抓取資料有兩個頭疼的點,寫過爬蟲的小夥伴們一定都深有體會:
- 網站的防抓取機制。你要儘可能將自己偽裝成“一個人”,騙過對方的伺服器反爬驗證。
- 網站的內容提取。每個網站都需要你做不同的處理,而且網站一旦改版,你的程式碼也得跟著更新。
第一點沒什麼捷徑可走,套路見得多了,也就有經驗了。關於第二點,今天我們們就來介紹一個小工具,在某些需求場景下,或許可以給你省不少事。
Goose
Goose 是一個文章內容提取器,可以從任意資訊文章類的網頁中提取文章主體,並提取標題、標籤、摘要、圖片、視訊等資訊,且支援中文網頁。它最初是由 http://Gravity.com 用 Java 編寫的。python-goose 是用 Python 重寫的版本。
有了這個庫,你從網上爬下來的網頁可以直接獲取正文內容,無需再用 bs4 或正規表示式一個個去處理文字。
專案地址:
(py2) https://github.com/grangier/python-goose
(py3) https://github.com/goose3/goose3
安裝
網上大多數教程提到的 python-goose 專案目前只支援到 python 2.7。可以通過 pip 安裝:
pip install goose-extractor
複製程式碼
或者安裝官網上的方法從原始碼安裝:
mkvirtualenv --no-site-packages goose
git clone https://github.com/grangier/python-goose.git
cd python-goose
pip install -r requirements.txt
python setup.py install
複製程式碼
我找到一個 python 3 的版本 goose3:
pip install goose3
複製程式碼
經過我一些簡單的測試,未發現兩個版本在結果上有太大的差異。
快速上手
這裡使用 goose3,而 python-goose 只要把其中的 goose3 改成 goose 即可,介面都是一樣的。以我之前發過的一篇文章 如何用Python抓抖音上的小姐姐 為抓取目標來做個演示。
from goose3 import Goose
from goose3.text import StopWordsChinese
# 初始化,設定中文分詞
g = Goose({'stopwords_class': StopWordsChinese})
# 文章地址
url = 'http://zhuanlan.zhihu.com/p/46396868'
# 獲取文章內容
article = g.extract(url=url)
# 標題
print('標題:', article.title)
# 顯示正文
print(article.cleaned_text)
複製程式碼
輸出:
除了標題 title 和正文 cleaned_text 外,還可以獲取一些額外的資訊,比如:
- meta_description:摘要
- meta_keywords:關鍵詞
- tags:標籤
- top_image:主要圖片
- infos:包含所有資訊的 dict
- raw_html:原始 HTML 文字
如有有些網站限制了程式抓取,也可以根據需要新增 user-agent 資訊:
g = Goose({'browser_user_agent': 'Version/5.1.2 Safari/534.52.7'})
複製程式碼
如果是 goose3,因為使用了 requests 庫作為請求模組,因此還可以以相似方式配置 headers、proxies 等屬性。
在上述示例中使用到的 StopWordsChinese
為中文分詞器,可一定程度上提高中文文章的識別準確率,但更耗時。
其他說明
1.
Goose 雖然方便,但並不能保證每個網站都能精確獲取,因此適合大規模文章的採集,如熱點追蹤、輿情分析等。它只能從概率上保證大多數網站可以相對準確地抓取。我經過一些嘗試後發現,抓取英文網站優於中文網站,主流網站優於小眾網站,文字的提取優於圖片的提取。
2.
從專案中的 requirements.txt 檔案可以看出,goose 中使用到了 Pillow、lxml、cssselect、jieba、beautifulsoup、nltk,goose3 還用到了 requests,我們之前很多文章和專案中都有所涉及:
這個男人讓你的爬蟲開發效率提升8倍
【程式設計課堂】jieba-中文分詞利器
3.
如果你是使用基於 python2 的 goose,有可能會遇到編碼上的問題(尤其是 windows 上)。這方面可以在公眾號對話裡回覆關鍵詞 編碼,我們有過相關的講解。
4.
除了 goose 外,還有其他的正文提取庫可以嘗試,比如 python-boilerpipe、python-readability 等。
例項
最後,我們來用 goose3 寫小一段程式碼,自動抓取 愛範兒、雷鋒網、DoNews 上的新聞文章:
from goose3 import Goose
from goose3.text import StopWordsChinese
from bs4 import BeautifulSoup
g = Goose({'stopwords_class': StopWordsChinese})
urls = [
'https://www.ifanr.com/',
'https://www.leiphone.com/',
'http://www.donews.com/'
]
url_articles = []
for url in urls:
page = g.extract(url=url)
soup = BeautifulSoup(page.raw_html, 'lxml')
links = soup.find_all('a')
for l in links:
link = l.get('href')
if link and link.startswith('http') and any(c.isdigit() for c in link if c) and link not in url_articles:
url_articles.append(link)
print(link)
for url in url_articles:
try:
article = g.extract(url=url)
content = article.cleaned_text
if len(content) > 200:
title = article.title
print(title)
with open('homework/goose/' + title + '.txt', 'w') as f:
f.write(content)
except:
pass
複製程式碼
這段程式所做的事情就是:
- 抓取網站首頁
- 從頁面上提取地址中帶有數字的連結(因為文章頁基本帶數字,這裡為了演示簡單以此判斷)
- 抓取這些連結,提取正文。如果結果超過 200 個字,就儲存成檔案
效果:
在此基礎上,你可以繼續改進這個程式,讓它不停地去尋找新的地址並抓取文章,並對獲取到的文章進行詞頻統計、生成詞雲等後續操作。類似我們之前的分析案例 資料分析:當趙雷唱民謠時他唱些什麼?。進一步完善,相信你能做出更有意思的專案。
相關程式碼已上傳,獲取地址請在公眾號(Crossin的程式設計教室)裡回覆關鍵字 goose
════
其他文章及回答:
如何自學Python | 新手引導 | 精選Python問答 | 如何debug? | Python單詞表 | 知乎下載器 | 人工智慧 | 嘻哈 | 爬蟲 | 我用Python | 高考 | requests | AI平臺
歡迎微信搜尋及關注:Crossin的程式設計教室