【python】六個(gè)常見爬蟲案例【附源碼】
共 27008字,需瀏覽 55分鐘
·
2024-05-07 08:35
整理了幾個(gè)常見的爬蟲案例,分享給大家,適合小白學(xué)習(xí)
一、爬取豆瓣電影排行榜Top250存儲(chǔ)到Excel文件
近年來,Python在和處理方面的應(yīng)用越來越廣泛。本文將介紹一個(gè)基于Python的爬蟲程序,用于抓取的相關(guān)信息,并將其保存為Excel文件。
獲取網(wǎng)頁(yè)數(shù)據(jù)的函數(shù),包括以下步驟: 1. 循環(huán)10次,依次爬取不同頁(yè)面的信息; 2. 使用urllib獲取html頁(yè)面; 3. 使用BeautifulSoup解析頁(yè)面; 4. 遍歷每個(gè)div標(biāo)簽,即每一部電影; 5. 對(duì)每個(gè)電影信息進(jìn)行匹配,使用正則表達(dá)式提取需要的信息并保存到一個(gè)列表中; 6. 將每個(gè)電影信息的列表保存到總列表中。
效果展示:
源代碼:
from bs4 import BeautifulSoup
import re #正則表達(dá)式,進(jìn)行文字匹配
import urllib.request,urllib.error #指定URL,獲取網(wǎng)頁(yè)數(shù)據(jù)
import xlwt #進(jìn)行excel操作
def main():
baseurl = "https://movie.douban.com/top250?start="
datalist= getdata(baseurl)
savepath = ".\\豆瓣電影top250.xls"
savedata(datalist,savepath)
#compile返回的是匹配到的模式對(duì)象
findLink = re.compile(r'<a href="(.*?)">') # 正則表達(dá)式模式的匹配,影片詳情
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) # re.S讓換行符包含在字符中,圖片信息
findTitle = re.compile(r'<span class="title">(.*)</span>') # 影片片名
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>') # 找到評(píng)分
findJudge = re.compile(r'<span>(\d*)人評(píng)價(jià)</span>') # 找到評(píng)價(jià)人數(shù) #\d表示數(shù)字
findInq = re.compile(r'<span class="inq">(.*)</span>') # 找到概況
findBd = re.compile(r'<p class="">(.*?)</p>', re.S) # 找到影片的相關(guān)內(nèi)容,如導(dǎo)演,演員等
##獲取網(wǎng)頁(yè)數(shù)據(jù)
def getdata(baseurl):
datalist=[]
for i in range(0,10):
url = baseurl+str(i*25) ##豆瓣頁(yè)面上一共有十頁(yè)信息,一頁(yè)爬取完成后繼續(xù)下一頁(yè)
html = geturl(url)
soup = BeautifulSoup(html,"html.parser") #構(gòu)建了一個(gè)BeautifulSoup類型的對(duì)象soup,是解析html的
for item in soup.find_all("div",class_='item'): ##find_all返回的是一個(gè)列表
data=[] #保存HTML中一部電影的所有信息
item = str(item) ##需要先轉(zhuǎn)換為字符串findall才能進(jìn)行搜索
link = re.findall(findLink,item)[0] ##findall返回的是列表,索引只將值賦值
data.append(link)
imgSrc = re.findall(findImgSrc, item)[0]
data.append(imgSrc)
titles=re.findall(findTitle,item) ##有的影片只有一個(gè)中文名,有的有中文和英文
if(len(titles)==2):
onetitle = titles[0]
data.append(onetitle)
twotitle = titles[1].replace("/","")#去掉無關(guān)的符號(hào)
data.append(twotitle)
else:
data.append(titles)
data.append(" ") ##將下一個(gè)值空出來
rating = re.findall(findRating, item)[0] # 添加評(píng)分
data.append(rating)
judgeNum = re.findall(findJudge, item)[0] # 添加評(píng)價(jià)人數(shù)
data.append(judgeNum)
inq = re.findall(findInq, item) # 添加概述
if len(inq) != 0:
inq = inq[0].replace("。", "")
data.append(inq)
else:
data.append(" ")
bd = re.findall(findBd, item)[0]
bd = re.sub('<br(\s+)?/>(\s+)?', " ", bd)
bd = re.sub('/', " ", bd)
data.append(bd.strip()) # 去掉前后的空格
datalist.append(data)
return datalist
##保存數(shù)據(jù)
def savedata(datalist,savepath):
workbook = xlwt.Workbook(encoding="utf-8",style_compression=0) ##style_compression=0不壓縮
worksheet = workbook.add_sheet("豆瓣電影top250",cell_overwrite_ok=True) #cell_overwrite_ok=True再次寫入數(shù)據(jù)覆蓋
column = ("電影詳情鏈接", "圖片鏈接", "影片中文名", "影片外國(guó)名", "評(píng)分", "評(píng)價(jià)數(shù)", "概況", "相關(guān)信息") ##execl項(xiàng)目欄
for i in range(0,8):
worksheet.write(0,i,column[i]) #將column[i]的內(nèi)容保存在第0行,第i列
for i in range(0,250):
data = datalist[i]
for j in range(0,8):
worksheet.write(i+1,j,data[j])
workbook.save(savepath)
##爬取網(wǎng)頁(yè)
def geturl(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
}
req = urllib.request.Request(url,headers=head)
try: ##異常檢測(cè)
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
except urllib.error.URLError as e:
if hasattr(e,"code"): ##如果錯(cuò)誤中有這個(gè)屬性的話
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
if __name__ == '__main__':
main()
print("爬取成功?。?!")
二、爬取百度熱搜排行榜Top50+可視化
2.1 代碼思路:
-
導(dǎo)入所需的庫(kù):
import requests
from bs4 import BeautifulSoup
import openpyxl
requests 庫(kù)用于發(fā)送HTTP請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容。BeautifulSoup 庫(kù)用于解析HTML頁(yè)面的內(nèi)容。openpyxl 庫(kù)用于創(chuàng)建和操作Excel文件。
2.發(fā)起HTTP請(qǐng)求獲取百度熱搜頁(yè)面內(nèi)容:
url = 'https://top.baidu.com/board?tab=realtime'
response = requests.get(url)
html = response.content
這里使用了 requests.get() 方法發(fā)送GET請(qǐng)求,并將響應(yīng)的內(nèi)容賦值給變量 html。
3.使用BeautifulSoup解析頁(yè)面內(nèi)容:
hot_searches = []
for item in soup.find_all('div', {'class': 'c-single-text-ellipsis'}):
hot_searches.append(item.text)
這段代碼通過調(diào)用 soup.find_all() 方法找到所有 <div> 標(biāo)簽,并且指定 class 屬性為 'c-single-text-ellipsis' 的元素。 然后,將每個(gè)元素的文本內(nèi)容添加到 hot_searches 列表中。
5.保存熱搜數(shù)據(jù)到Excel:
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = 'Baidu Hot Searches'
使用 openpyxl.Workbook() 創(chuàng)建一個(gè)新的工作簿對(duì)象。 調(diào)用 active 屬性獲取當(dāng)前活動(dòng)的工作表對(duì)象,并將其賦值給變量 sheet。 使用 title 屬性給工作表命名為 'Baidu Hot Searches'。
7.寫入熱搜數(shù)據(jù):
for i in range(len(hot_searches)):
sheet.cell(row=i+2, column=1, value=hot_searches[i])
使用 range() 函數(shù)生成一個(gè)包含索引的范圍,循環(huán)遍歷 hot_searches 列表。 對(duì)于每個(gè)索引 i,使用 cell() 方法將對(duì)應(yīng)的熱搜詞寫入Excel文件中。
8.保存Excel文件:
workbook.save('百度熱搜.xlsx')
使用 save() 方法將工作簿保存到指定的文件名 '百度熱搜.xlsx'。
9.輸出提示信息:
print('熱搜數(shù)據(jù)已保存到 百度熱搜.xlsx')
在控制臺(tái)輸出保存成功的提示信息。
效果展示:
源代碼:
import requests
from bs4 import BeautifulSoup
import openpyxl
# 發(fā)起HTTP請(qǐng)求獲取百度熱搜頁(yè)面內(nèi)容
url = 'https://top.baidu.com/board?tab=realtime'
response = requests.get(url)
html = response.content
# 使用BeautifulSoup解析頁(yè)面內(nèi)容
soup = BeautifulSoup(html, 'html.parser')
# 提取熱搜數(shù)據(jù)
hot_searches = []
for item in soup.find_all('div', {'class': 'c-single-text-ellipsis'}):
hot_searches.append(item.text)
# 保存熱搜數(shù)據(jù)到Excel
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = 'Baidu Hot Searches'
# 設(shè)置標(biāo)題
sheet.cell(row=1, column=1, value='百度熱搜排行榜—博主:Yan-英杰')
# 寫入熱搜數(shù)據(jù)
for i in range(len(hot_searches)):
sheet.cell(row=i+2, column=1, value=hot_searches[i])
workbook.save('百度熱搜.xlsx')
print('熱搜數(shù)據(jù)已保存到 百度熱搜.xlsx')
可視化代碼:
import requests
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
# 發(fā)起HTTP請(qǐng)求獲取百度熱搜頁(yè)面內(nèi)容
url = 'https://top.baidu.com/board?tab=realtime'
response = requests.get(url)
html = response.content
# 使用BeautifulSoup解析頁(yè)面內(nèi)容
soup = BeautifulSoup(html, 'html.parser')
# 提取熱搜數(shù)據(jù)
hot_searches = []
for item in soup.find_all('div', {'class': 'c-single-text-ellipsis'}):
hot_searches.append(item.text)
# 設(shè)置中文字體
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 繪制條形圖
plt.figure(figsize=(15, 10))
x = range(len(hot_searches))
y = list(reversed(range(1, len(hot_searches)+1)))
plt.barh(x, y, tick_label=hot_searches, height=0.8) # 調(diào)整條形圖的高度
# 添加標(biāo)題和標(biāo)簽
plt.title('百度熱搜排行榜')
plt.xlabel('排名')
plt.ylabel('關(guān)鍵詞')
# 調(diào)整坐標(biāo)軸刻度
plt.xticks(range(1, len(hot_searches)+1))
# 調(diào)整條形圖之間的間隔
plt.subplots_adjust(hspace=0.8, wspace=0.5)
# 顯示圖形
plt.tight_layout()
plt.show()
三、爬取斗魚直播照片保存到本地目錄
效果展示:
源代碼:
#導(dǎo)入了必要的模塊requests和os
import requests
import os
# 定義了一個(gè)函數(shù)get_html(url),
# 用于發(fā)送GET請(qǐng)求獲取指定URL的響應(yīng)數(shù)據(jù)。函數(shù)中設(shè)置了請(qǐng)求頭部信息,
# 以模擬瀏覽器的請(qǐng)求。函數(shù)返回響應(yīng)數(shù)據(jù)的JSON格式內(nèi)容
def get_html(url):
header = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
}
response = requests.get(url=url, headers=header)
# print(response.json())
html = response.json()
return html
# 定義了一個(gè)函數(shù)parse_html(html),
# 用于解析響應(yīng)數(shù)據(jù)中的圖片信息。通過分析響應(yīng)數(shù)據(jù)的結(jié)構(gòu),
# 提取出每個(gè)圖片的URL和標(biāo)題,并將其存儲(chǔ)在一個(gè)字典中,然后將所有字典組成的列表返回
def parse_html(html):
rl_list = html['data']['rl']
# print(rl_list)
img_info_list = []
for rl in rl_list:
img_info = {}
img_info['img_url'] = rl['rs1']
img_info['title'] = rl['nn']
# print(img_url)
# exit()
img_info_list.append(img_info)
# print(img_info_list)
return img_info_list
# 定義了一個(gè)函數(shù)save_to_images(img_info_list),用于保存圖片到本地。
# 首先創(chuàng)建一個(gè)目錄"directory",如果目錄不存在的話。然后遍歷圖片信息列表,
# 依次下載每個(gè)圖片并保存到目錄中,圖片的文件名為標(biāo)題加上".jpg"后綴。
def save_to_images(img_info_list):
dir_path = 'directory'
if not os.path.exists(dir_path):
os.makedirs(dir_path)
for img_info in img_info_list:
img_path = os.path.join(dir_path, img_info['title'] + '.jpg')
res = requests.get(img_info['img_url'])
res_img = res.content
with open(img_path, 'wb') as f:
f.write(res_img)
# exit()
#在主程序中,設(shè)置了要爬取的URL,并調(diào)用前面定義的函數(shù)來執(zhí)行爬取、解析和保存操作。
if __name__ == '__main__':
url = 'https://www.douyu.com/gapi/rknc/directory/yzRec/1'
html = get_html(url)
img_info_list = parse_html(html)
save_to_images(img_info_list)
四、爬取酷狗音樂Top500排行榜
從酷狗音樂排行榜中提取歌曲的排名、歌名、歌手和時(shí)長(zhǎng)等信息
代碼思路:
效果展示:
源碼:
import requests # 發(fā)送網(wǎng)絡(luò)請(qǐng)求,獲取 HTML 等信息
from bs4 import BeautifulSoup # 解析 HTML 信息,提取需要的信息
import time # 控制爬蟲速度,防止過快被封IP
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36"
# 添加瀏覽器頭部信息,模擬請(qǐng)求
}
def get_info(url):
# 參數(shù) url :要爬取的網(wǎng)頁(yè)地址
web_data = requests.get(url, headers=headers) # 發(fā)送網(wǎng)絡(luò)請(qǐng)求,獲取 HTML 等信息
soup = BeautifulSoup(web_data.text, 'lxml') # 解析 HTML 信息,提取需要的信息
# 通過 CSS 選擇器定位到需要的信息
ranks = soup.select('span.pc_temp_num')
titles = soup.select('div.pc_temp_songlist > ul > li > a')
times = soup.select('span.pc_temp_tips_r > span')
# for 循環(huán)遍歷每個(gè)信息,并將其存儲(chǔ)到字典中
for rank, title, time in zip(ranks, titles, times):
data = {
"rank": rank.get_text().strip(), # 歌曲排名
"singer": title.get_text().replace("\n", "").replace("\t", "").split('-')[1], # 歌手名
"song": title.get_text().replace("\n", "").replace("\t", "").split('-')[0], # 歌曲名
"time": time.get_text().strip() # 歌曲時(shí)長(zhǎng)
}
print(data) # 打印獲取到的信息
if __name__ == '__main__':
urls = ["https://www.kugou.com/yy/rank/home/{}-8888.html".format(str(i)) for i in range(1, 24)]
# 構(gòu)造要爬取的頁(yè)面地址列表
for url in urls:
get_info(url) # 調(diào)用函數(shù),獲取頁(yè)面信息
time.sleep(1) # 控制爬蟲速度,防止過快被封IP
五、爬取鏈家二手房數(shù)據(jù)做數(shù)據(jù)分析
在和挖掘領(lǐng)域中,網(wǎng)絡(luò)爬蟲是一種常見的工具,用于從網(wǎng)頁(yè)上收集數(shù)據(jù)。介紹如何使用 Python 編寫簡(jiǎn)單的網(wǎng)絡(luò)爬蟲程序,從鏈家網(wǎng)上海二手房頁(yè)面獲取房屋信息,并將數(shù)據(jù)保存到 Excel 文件中。
效果圖:
代碼思路:
首先,我們定義了一個(gè)函數(shù) fetch_data(page_number),用于獲取指定頁(yè)面的房屋信息數(shù)據(jù)。這個(gè)函數(shù)會(huì)構(gòu)建對(duì)應(yīng)頁(yè)數(shù)的 URL,并發(fā)送 GET 請(qǐng)求獲取頁(yè)面內(nèi)容。然后,使用 BeautifulSoup 解析頁(yè)面內(nèi)容,并提取每個(gè)房屋信息的相關(guān)數(shù)據(jù),如區(qū)域、房型、關(guān)注人數(shù)、單價(jià)和總價(jià)。最終將提取的數(shù)據(jù)以字典形式存儲(chǔ)在列表中,并返回該列表。
接下來,我們定義了主函數(shù) main(),該函數(shù)控制整個(gè)爬取和保存數(shù)據(jù)的流程。在主函數(shù)中,我們循環(huán)爬取前 10 頁(yè)的數(shù)據(jù),調(diào)用 fetch_data(page_number) 函數(shù)獲取每一頁(yè)的數(shù)據(jù),并將數(shù)據(jù)追加到列表中。然后,將所有爬取的數(shù)據(jù)存儲(chǔ)在 DataFrame 中,并使用 df.to_excel('lianjia_data.xlsx', index=False) 將數(shù)據(jù)保存到 Excel 文件中。
最后,在程序的入口處,通過 if name == "main": 來執(zhí)行主函數(shù) main()。
源代碼:
import requests
from bs4 import BeautifulSoup
import pandas as pd
# 收集單頁(yè)數(shù)據(jù) xpanx.com
def fetch_data(page_number):
url = f"https://sh.lianjia.com/ershoufang/pg{page_number}/"
response = requests.get(url)
if response.status_code != 200:
print("請(qǐng)求失敗")
return []
soup = BeautifulSoup(response.text, 'html.parser')
rows = []
for house_info in soup.find_all("li", {"class": "clear LOGVIEWDATA LOGCLICKDATA"}):
row = {}
# 使用您提供的類名來獲取數(shù)據(jù) xpanx.com
row['區(qū)域'] = house_info.find("div", {"class": "positionInfo"}).get_text() if house_info.find("div", {
"class": "positionInfo"}) else None
row['房型'] = house_info.find("div", {"class": "houseInfo"}).get_text() if house_info.find("div", {
"class": "houseInfo"}) else None
row['關(guān)注'] = house_info.find("div", {"class": "followInfo"}).get_text() if house_info.find("div", {
"class": "followInfo"}) else None
row['單價(jià)'] = house_info.find("div", {"class": "unitPrice"}).get_text() if house_info.find("div", {
"class": "unitPrice"}) else None
row['總價(jià)'] = house_info.find("div", {"class": "priceInfo"}).get_text() if house_info.find("div", {
"class": "priceInfo"}) else None
rows.append(row)
return rows
# 主函數(shù)
def main():
all_data = []
for i in range(1, 11): # 爬取前10頁(yè)數(shù)據(jù)作為示例
print(f"正在爬取第{i}頁(yè)...")
all_data += fetch_data(i)
# 保存數(shù)據(jù)到Excel xpanx.com
df = pd.DataFrame(all_data)
df.to_excel('lianjia_data.xlsx', index=False)
print("數(shù)據(jù)已保存到 'lianjia_data.xlsx'")
if __name__ == "__main__":
main()
六、爬取豆瓣電影排行榜TOP250存儲(chǔ)到CSV文件中
代碼思路:
首先,我們導(dǎo)入了需要用到的三個(gè)Python模塊:requests、lxml和csv。 然后,我們定義了豆瓣電影TOP250頁(yè)面的URL地址,并使用getSource(url)函數(shù)獲取網(wǎng)頁(yè)源碼。
接著,我們定義了一個(gè)getEveryItem(source)函數(shù),它使用XPath表達(dá)式從HTML源碼中提取出每部電影的標(biāo)題、URL、評(píng)分和引言,并將這些信息存儲(chǔ)到一個(gè)字典中,最后將所有電影的字典存儲(chǔ)到一個(gè)列表中并返回。
然后,我們定義了一個(gè)writeData(movieList)函數(shù),它使用csv庫(kù)的DictWriter類創(chuàng)建一個(gè)CSV寫入對(duì)象,然后將電影信息列表逐行寫入CSV文件。
最后,在if name == 'main'語(yǔ)句塊中,我們定義了一個(gè)空的電影信息列表movieList,然后循環(huán)遍歷前10頁(yè)豆瓣電影TOP250頁(yè)面,分別抓取每一頁(yè)的網(wǎng)頁(yè)源碼,并使用getEveryItem()函數(shù)解析出電影信息并存儲(chǔ)到movieList中,最后使用writeData()函數(shù)將電影信息寫入CSV文件。
效果圖:
源代碼:
#代碼首先導(dǎo)入了需要使用的模塊:requests、lxml和csv。
import requests
from lxml import etree
import csv
#
doubanUrl = 'https://movie.douban.com/top250?start={}&filter='
# 然后定義了豆瓣電影TOP250頁(yè)面的URL地址,并實(shí)現(xiàn)了一個(gè)函數(shù)getSource(url)來獲取網(wǎng)頁(yè)的源碼。該函數(shù)發(fā)送HTTP請(qǐng)求,添加了請(qǐng)求頭信息以防止被網(wǎng)站識(shí)別為爬蟲,并通過requests.get()方法獲取網(wǎng)頁(yè)源碼。
def getSource(url):
# 反爬 填寫headers請(qǐng)求頭
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
response = requests.get(url, headers=headers)
# 防止出現(xiàn)亂碼
response.encoding = 'utf-8'
# print(response.text)
return response.text
# 定義了一個(gè)函數(shù)getEveryItem(source)來解析每個(gè)電影的信息。首先,使用lxml庫(kù)的etree模塊將源碼轉(zhuǎn)換為HTML元素對(duì)象。然后,使用XPath表達(dá)式定位到包含電影信息的每個(gè)HTML元素。通過對(duì)每個(gè)元素進(jìn)行XPath查詢,提取出電影的標(biāo)題、副標(biāo)題、URL、評(píng)分和引言等信息。最后,將這些信息存儲(chǔ)在一個(gè)字典中,并將所有電影的字典存儲(chǔ)在一個(gè)列表中。
def getEveryItem(source):
html_element = etree.HTML(source)
movieItemList = html_element.xpath('//div[@class="info"]')
# 定義一個(gè)空的列表
movieList = []
for eachMoive in movieItemList:
# 創(chuàng)建一個(gè)字典 像列表中存儲(chǔ)數(shù)據(jù)[{電影一},{電影二}......]
movieDict = {}
title = eachMoive.xpath('div[@class="hd"]/a/span[@class="title"]/text()') # 標(biāo)題
otherTitle = eachMoive.xpath('div[@class="hd"]/a/span[@class="other"]/text()') # 副標(biāo)題
link = eachMoive.xpath('div[@class="hd"]/a/@href')[0] # url
star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()')[0] # 評(píng)分
quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()') # 引言(名句)
if quote:
quote = quote[0]
else:
quote = ''
# 保存數(shù)據(jù)
movieDict['title'] = ''.join(title + otherTitle)
movieDict['url'] = link
movieDict['star'] = star
movieDict['quote'] = quote
movieList.append(movieDict)
print(movieList)
return movieList
# 保存數(shù)據(jù)
def writeData(movieList):
with open('douban.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['title', 'star', 'quote', 'url'])
writer.writeheader() # 寫入表頭
for each in movieList:
writer.writerow(each)
if __name__ == '__main__':
movieList = []
# 一共有10頁(yè)
for i in range(10):
pageLink = doubanUrl.format(i * 25)
source = getSource(pageLink)
movieList += getEveryItem(source)
writeData(movieList)
