專注Python/ target=_blank class=infotextkey>Python、AI、大數(shù)據(jù),請關(guān)注公眾號七步編程!
在不同公司的許多人可能出于各種原因需要從Inte.NET收集外部數(shù)據(jù):分析競爭,匯總新聞?wù)⒏櫶囟ㄊ袌龅内厔荩蛘呤占咳展善眱r格以建立預(yù)測模型……
無論你是數(shù)據(jù)科學(xué)家還是業(yè)務(wù)分析師,都可能時不時遇到這種情況,并問自己一個永恒的問題:我如何才能提取該網(wǎng)站的數(shù)據(jù)以進行市場分析?
提取網(wǎng)站數(shù)據(jù)及其結(jié)構(gòu)的一種可能的免費方法是爬蟲。
在本文中,你將了解如何通過Python輕松的完成數(shù)據(jù)爬蟲任務(wù)。
什么是爬蟲?
廣義上講,數(shù)據(jù)爬蟲是指以編程方式提取網(wǎng)站數(shù)據(jù)并根據(jù)其需求進行結(jié)構(gòu)化的過程。
許多公司正在使用數(shù)據(jù)爬蟲來收集外部數(shù)據(jù)并支持其業(yè)務(wù)運營:這是當(dāng)前在多個領(lǐng)域中普遍的做法。
我需要了解什么才能學(xué)習(xí)python中的數(shù)據(jù)抓取?
很簡單,但是需要首先具備一些Python和html知識。
另外,需要了解兩個非常有效的框架,例如,Scrapy或Selenium。
詳細介紹
接下來,讓我們學(xué)習(xí)如何將網(wǎng)站變成結(jié)構(gòu)化數(shù)據(jù)!
為此,首先需要安裝以下庫:
- requests:模擬HTTP請求(例如GET和POST), 我們將主要使用它來訪問任何給定網(wǎng)站的源代碼
- BeautifulSoup:輕松解析HTML和XML數(shù)據(jù)
- lxml:提高XML文件的解析速度
- pandas:將數(shù)據(jù)構(gòu)造為Dataframes并以您選擇的格式(JSON,Excel,CSV等)導(dǎo)出
如果你使用的是Anaconda,配置起來會非常簡單,這些軟件包都已預(yù)先安裝。
如果不是使用Anaconda,需要通過如下命令安裝工具包:
pip install requests
pip install beautifulsoup4
pip install lxml
pip install pandas
我們要抓取哪些網(wǎng)站和數(shù)據(jù)?
這是爬蟲過程中首先需要回答的問題。
本文就以爬取Premium Beauty News為例進行演示。
該以優(yōu)質(zhì)美容新聞為主,它發(fā)布了美容市場的最新趨勢。
查看首頁,你會看到我們要抓取的文章以網(wǎng)格形式組織。
多頁面的組織如下:
當(dāng)然,我們僅要提取出現(xiàn)在這些頁面上的每篇文章的標題,我們將深入每個帖子并獲取我們需要的詳細內(nèi)容,例如:
- 標題
- 日期
- 摘要
- 全文
編碼實踐
前面,已經(jīng)介紹了基本的內(nèi)容以及需要用到的工具包。
接下來,就是正式編碼實踐的步驟。
首先,需要導(dǎo)入基礎(chǔ)工具包:
import requests
from bs4 import BeautifulSoup
import pandas as pd
from tqdm import tqdm_notebook
我通常定義一個函數(shù)來解析給定URL的每個頁面的內(nèi)容。
該函數(shù)將被多次調(diào)用,這里將他命名為parse_url:
def parse_url(url):
response = requests.get(url)
content = response.content
parsed_response = BeautifulSoup(content, "lxml")
return parsed_response
提取每個帖子數(shù)據(jù)和元數(shù)據(jù)
首先,我將定義一個函數(shù),該函數(shù)提取給定URL的每個帖子的數(shù)據(jù)(標題,日期,摘要等)。
然后,我們將遍歷所有頁面的for循環(huán)內(nèi)調(diào)用此函數(shù)。
要構(gòu)建我們的爬蟲工具,我們首先必須了解頁面的基本HTML邏輯和結(jié)構(gòu)。以提取帖子的標題為例,講解一下。
通過在Chrome檢查器中檢查此元素:
我們注意到標題出現(xiàn)在 article-title類的h1內(nèi)。
使用BeautifulSoup提取頁面內(nèi)容后,可以使用find方法提取標題。
title = soup_post.find("h1", {"class": "article-title"}).text
接下來,看一下日期:
該日期顯示在一個span內(nèi),該范圍本身顯示在row sub-header類的標題內(nèi)。
使用BeautifulSoup將其轉(zhuǎn)換為代碼非常容易:
datetime = soup_post.find("header", {"class": "row sub- header"}).find("span")["datetime"]
下一步就是摘要:
它在article-intro的h2標簽下:
abstract = soup_post.find("h2", {"class": "article-intro"}).text
現(xiàn)在,需要爬取帖子的全文內(nèi)容。如果已經(jīng)理解了前面的內(nèi)容,那么這部分會非常容易。
該內(nèi)容在article-text類的div內(nèi)的多個段落(p標簽)中。
BeautifulSoup可以通過以下一種方式提取完整的文本。而不是遍歷每個每個p標簽、提取文本、然后將所有文本連接在一起。
content = soup_post.find("div", {"class": "article-text"}).text
下面,讓我們把它們放在同一個函數(shù)內(nèi)看一下:
def extract_post_data(post_url):
soup_post = parse_url(post_url)
title = soup_post.find("h1", {"class": "article-title"}).text
datetime = soup_post.find("header", {"class": "row sub-header"}).find("span")["datetime"]
abstract = soup_post.find("h2", {"class": "article-intro"}).text
content = soup_post.find("div", {"class": "article-text"}).text
data = {
"title": title,
"datetime": datetime,
"abstract": abstract,
"content": content,
"url": post_url
}
return data
提取多個頁面上的帖子URL
如果我們檢查主頁的源代碼,會看到每個頁面文章的標題:
可以看到,每10篇文章出現(xiàn)在1個post-style1 col-md-6標簽下:
下面,提取每個頁面的文章就很容易了:
url = "https://www.premiumbeautynews.com/fr/marches-tendances/"
soup = parse_url(url)
section = soup.find("section", {"class": "content"})
posts = section.findAll("div", {"class": "post-style1 col-md-6"})
然后,對于每個單獨的帖子,我們可以提取URL,該URL出現(xiàn)在h4標簽內(nèi)部。
我們將使用此URL調(diào)用我們先前定義的函數(shù)extract_post_data。
uri = post.find("h4").find("a")["href"]
分頁
在給定頁面上提取帖子后,需要轉(zhuǎn)到下一頁并重復(fù)相同的操作。
如果查看分頁,需要點擊“下一個”按鈕:
到達最后一頁后,此按鈕變?yōu)闊o效。
換句話說,當(dāng)下一個按鈕處于有效狀態(tài)時,就需要執(zhí)行爬蟲操作,移至下一頁并重復(fù)該操作。當(dāng)按鈕變?yōu)闊o效狀態(tài)時,該過程應(yīng)停止。
總結(jié)此邏輯,這將轉(zhuǎn)換為以下代碼:
next_button = ""
posts_data = []
count = 1
base_url = 'https://www.premiumbeautynews.com/'
while next_button isnotNone:
print(f"page number : {count}")
soup = parse_url(url)
section = soup.find("section", {"class": "content"})
posts = section.findAll("div", {"class": "post-style1 col-md-6"})
for post in tqdm_notebook(posts, leave=False):
uri = post.find("h4").find("a")["href"]
post_url = base_url + uri
data = extract_post_data(post_url)
posts_data.Append(data)
next_button = soup.find("p", {"class": "pagination"}).find("span", {"class": "next"})
if next_button isnotNone:
url = base_url + next_button.find("a")["href"]
count += 1
此循環(huán)完成后,將所有數(shù)據(jù)保存在posts_data中,可以將其轉(zhuǎn)換為漂亮的DataFrames并導(dǎo)出為CSV或Excel文件。
df = pd.DataFrame(posts_data)
df.head()
到這里,就把一個非結(jié)構(gòu)化的網(wǎng)頁轉(zhuǎn)化成結(jié)構(gòu)化的數(shù)據(jù)了!






