python 網路爬蟲全流程教學,從入門到實戰(requests+bs4+存儲文件)
python 網路爬蟲全流程教學,從入門到實戰(requests+bs4+存儲文件)
requests是一個Python第三方庫,用於向URL地址發起請求
bs4 全名 BeautifulSoup4,是編寫 python 爬蟲常用庫之一,主要用來解析 html 標籤。
一、爬蟲編寫過程解析
1.1 導入庫文件(請求庫、解析庫)
#導入 requests請求庫
import requests
#導入bs4解析庫
from bs4 import BeautifulSoup
1.2 發起對指定網頁的請求
#對爬取網頁的鏈接
url='請求地址'
#請求頭(作用:為了不被對方發現是爬蟲的訪問)
#去需要爬取網頁上>打開開發者模式(F12)>網路(network)>隨便點開一個文件>標頭>請求頭裡的User-Agent
headers={'User-Agent': '請求頭'}
#發起get請求,獲取請求內容,並用(utf-8)解碼(編碼一般是:utf-8,gbk,gb2312)
html=requests.get(headers=headers,url=url).content.decode('utf-8')
1.3 解析為 bs4格式
#解析為bs4,BeautifulSoup(html文本,'解析器'),如下表
soup=BeautifulSoup(html,'html.parser')
如果一段HTML或XML文檔格式不正確的話,那麼在不同的解析器中返回的結果可能是不一樣的。
解析器 | 使用方法 | 優勢 |
---|---|---|
Python標準庫 | BeautifulSoup(html, “html.parser”) | 1、Python的內置標準庫 2、執行速度適中 3、文檔容錯能力強 |
lxml HTML | BeautifulSoup(html, “lxml”) | 1、速度快 2、文檔容錯能力強 |
lxml XML | BeautifulSoup(html, [“lxml”, “xml”]) BeautifulSoup(html, “xml”) | 1、速度快 2、唯一支援XML的解析器 |
html5lib | BeautifulSoup(html, “html5lib”) | 1、最好的容錯性 2、以瀏覽器的方式解析文檔 3、生成HTML5格式的文檔 |
1.4 解析獲取的內容(獲取想要的數據)
#獲取想要的網頁標籤(如div)
Tdiv=soup.find_all('div',class_="div的class樣式名")
#輸出查找到的結構
print(Tdiv)
1.5 存儲爬取的數據
#格式
with open('./文件路徑/文件名.文件類型','許可權') as f:
f.write('字元型文本')
二、bs4核心函數
作用:獲取,網頁中的各個自己想要的標籤,一般是從大標籤到小標籤的過程
操作案例百度
#導入庫
from bs4 import BeautifulSoup
import requests
#百度的url地址
url="//www.baidu.com/"
#請求頭(作用:為了不被對方發現是爬蟲的訪問)
hearders={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.53'}
#獲取百度的請求
html=requests.get(url=url, headers=hearders).content.decode("utf-8")
#解析為bs4
soup = BeautifulSoup(html,"html.parser")
2.1 find()
查找符合條件的第一個標籤,結果是標籤對象
find( name , attrs/class_ , recursive , string , **kwargs )
soup.find(‘標籤名’,屬性名=「屬性」/class_=”類名”,recursive=「是否只要子節點(默認False)」,string=”標籤內容”)
參數可以任意組合或只填寫一個
①根據標籤名定位第一個指定的標籤
#查詢出第一個p標籤對象,並輸出
print(soup.find('p'))
#查詢出第一個a標籤對象,並輸出
print(soup.find('a'))
②根據屬性名定位滿足條件的第一個標籤
#查詢class屬性為』s-top-wrap s-isindex-wrap『的任意標籤
print(soup.find_all(class_='s-top-wrap s-isindex-wrap'))
#查詢id屬性為s_top_wrap的所有標籤,其他屬性名照寫
print(soup.find_all(id='s_top_wrap'))
③根據標籤和標籤屬性定位
#查詢class為』s-top-wrap s-isindex-wrap『的一個div標籤
print(soup.find('div',class_='s-top-wrap s-isindex-wrap'))
#查詢id為s_top_wrap的第一個div標籤
print(soup.find('div',id='s_top_wrap'))
④根據指定的標籤名和對應的標籤內容定位
#查詢到內容為「設置「的第一個span標籤
print(soup.find('span',string="設置"))
2.2 find_all()
和
find()
函數用法一樣,不同之處在於find()
只返回滿足條件的第一個標籤對象,而find_all()
返回所有滿足條件的標籤對象,是一個列表
。有時需要兩個配合使用。
①根據標籤名定位所有指定的標籤
#查詢所有是img的標籤,返回的是一個列表
print(soup.find_all('img'))
②根據屬性名定位所有滿足條件的標籤
#查詢所有class屬性為』s-top-wrap s-isindex-wrap『的任意標籤
print(soup.find_all(class_='s-top-wrap s-isindex-wrap'))
#查詢id屬性為s_top_wrap的所有標籤,其他屬性名照寫
print(soup.find_all(id='s_top_wrap'))
③根據指定的標籤和對應的屬性名定位所有滿足條件的標籤
#查詢所有class屬性為's-top-wrap s-isindex-wrap'的div標籤
print(soup.find_all('div',class_='s-top-wrap s-isindex-wrap'))
#查詢所有id屬性為's_top_wrap'的div的標籤
print(soup.find_all('div',id='s_top_wrap'))
④根據指定的標籤名和對應的標籤內容定位
#查詢內容為「設置「的所有span標籤
print(soup.find_all('span',string="設置"))
2.3 select()
select()
函數也是定位所有滿足條件的標籤,返回值也是一個列表
①根據標籤名定位
#查詢所有是img的標籤,返回的是一個列表
print(soup.select("img"))
②根據標籤名和屬性定位
#查詢class屬性為』s-top-wrap『的所有標籤
print(soup.select('.s-top-wrap'))
#查詢id屬性為『s_top_wrap'的所有標籤
print(soup.select('#s_top_wrap'))
#通過標籤名和屬性一起配合查詢,其他屬性直接寫對應的屬性如:a[hrsr='https']
print(soup.select('div[id="s_top_wrap"]'))
③定位對應的子標籤
#查所有a標籤下的img標籤
print(soup.select('a>img'))
三、bs4基本操作
作用:獲取標籤中自己想要的內容,如:文字、圖片鏈接、影片鏈接、音頻鏈接等
注意:soup只是一個變數,就是你查詢出來後新的獲取範圍
3.1 獲取標籤內的文本
#分別獲取a標籤和p標籤內的文本內容(推薦第一種方式)
print(soup.a.text)
pring(soup.p.string)
3.2 獲取標籤屬性
#獲取第一個div標籤的所有屬性
print(soup.div.attrs)
3.3 獲取指定標籤的屬性值
#獲取div標籤中的class屬性的值
print(soup.div.attrs.get('class'))
#獲取div標籤中的id屬性的值
print(soup.div.get('id'))
#獲取img標籤中的src屬性的值
print(soup.img.get('src'))
3.4 遍歷獲取的標籤的屬性值
#獲取到所有的img標籤,返回值為列表
imgs=soup.find_all('img')
for i in imgs:
#img標籤中src的值
print(i['src'])
#獲取到所有的img標籤,返回值為列表
imgs=soup.find_all('img')
for i in imgs:
#img標籤中src的值
print(i.get('src'))
3.5 獲取指定標籤內所有的元素
print(soup.p.contents)
3.6 獲取標籤的父標籤
print(soup.a.parent)
四、存儲數據
存儲為:文本文檔(txt)、表格(excel)、圖片、音頻、影片
注意:本章節只講解寫操作,寫出什麼文件寫什麼格式
4.1 with open() as f: 用法
#格式
with open('./文件路徑/文件名.文件類型','許可權') as f:
f.write('字元型文本')
許可權 | 作用 |
---|---|
w | 寫入,新的會覆蓋舊的 |
a | 寫入,在末尾追加寫入,不會覆蓋舊的 |
wb | 寫入,以二進位的方式寫入(圖片、音頻、影片) |
4.2 寫入為文本文檔(txt)
#將變數里的內容寫入到「文本.txt」文件中,沒有"文本.txt"會自動創建
wb='我是被爬取下來的文字'
with open('文本.txt','w') as f:
f.write(wb)
4.3 循環寫入到文本文檔中(txt)
#將列表裡的內容循環到「文本.txt」文件中,沒有"文本.txt"會自動創建
wb=['文本1','文本2','文本3','文本4']
for i in wb:
with open('文本.txt','a') as f:
f.write(i)
4.4 存儲圖片
#導入請求庫
import requests
#請求頭
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42'}
#圖片地址列表
imgs=['//img-blog.csdnimg.cn/a263ea6716ff44d4a2a825dbf26d2666.png','//img-blog.csdnimg.cn/43112c81ed164acfb45295f516d08925.png']
#為圖片命名的變數
i=1
#遍歷圖片地址
for img in imgs:
#向圖片地址發起請求,並且獲取請求內容
res=requests.get(url=img,headers=headers).content
#寫出圖片(注意:許可權是wb,寫圖片擴展名和獲取的圖片保存一致)
with open(str(i)+'.png','wb') as f:
#寫出的參數為請求回來的內容
f.write(res)
i+=1
print("寫出成功!")
4.5 存儲影片
寫出音頻也是如此
#導入庫
import requests
#請求頭
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42'}
#影片地址
video='//prod-streaming-video-msn-com.akamaized.net/3f6ca508-598d-4cbd-a3e2-43deea7bc377/b60c553e-9f3f-4164-8850-700a9a73a899.mp4'
#發起請求
res=requests.get(url=video,headers=headers).content
#寫出影片
with open('影片.mp4','wb') as f:
f.write(res)
print("寫出成功!")
4.6 存儲為excel
sheet.write(行,列,內容)
注意:行和列都是從0開始的,保存的格式為:.xls
#導入寫出excel的庫
import xlwt
#寫入的數據
tn=['姓名','性別','年齡']
wb=['玲華','女','18']
#1、創建Workbook對象,就是創建Excel文件
work_boot=xlwt.Workbook(encoding='utf-8');
#2、創建sheet表單
sheet=work_boot.add_sheet('formName') #formName為表單名稱
#3、寫入內容
for i in range(len(wb)):
sheet.write(0,i,tn[i]) #write(行,列,內容)
sheet.write(1,i,wb[i])
#保存文件
work_boot.save("個人資訊.xls")
五、爬蟲實戰操作
實戰是需要自己去分析網頁結構的,部落客程式碼只是一種參考,還是要自己去分析。
5.1 百度熱搜榜
獲取標題、熱度、簡介、新聞鏈接、圖片、文本保存為txt,並輸出
注意:這裡沒有自動創建保存文件的文件夾,自行修改
#導入庫文件
import requests
from bs4 import BeautifulSoup
#請求頭
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42'}
#請求地址
url='//top.baidu.com/board?tab=realtime'
def Hot_search():
#發起請求
html=requests.get(url=url,headers=headers).text;
#解析為bs4
res=BeautifulSoup(html,"html.parser")
#獲取類名獲取指定的div(包含所有的新聞資訊)
news_div=res.find_all("div",class_="category-wrap_iQLoo horizontal_1eKyQ")
#遍歷div(提取每一個新聞)
for new in news_div:
try:
#獲取新聞的標題(標題在下標為0的地方,獲取文本)
title=new.find_all("div",class_="c-single-text-ellipsis")[0].text
#獲取新聞的熱度(熱度在下標為0的地方,獲取文本)
hot=new.find_all("div",class_="hot-index_1Bl1a")[0].text
#獲取新聞的簡介(簡介在下標為0的地方,獲取文本)
conent=new.find_all("div",class_="hot-desc_1m_jR small_Uvkd3 ellipsis_DupbZ")[0].text
#獲取新聞的鏈接(通過第一個a標籤,的href屬性獲取)
newUrl=new.find('a').attrs.get('href')
#獲取要下載的圖片鏈接的img標籤(標籤在下標為0的地方)
imgUrl=new.find_all("img")[0]
#獲取要下載的圖片鏈接(通過img的src屬性獲取)
imgUrl=imgUrl.attrs.get('src')
print('\n'+'標題:' + str(title) + '\n' + '熱度:' + str(hot) + '\n' + '簡介:' + str(conent) + '\n' + '新聞鏈接:' + str(newUrl) + '\n\n')
#請求圖片
img=requests.get(url=imgUrl,headers=headers).content
#寫出圖片
with open('./百度熱搜/' + str(title.strip()) + '.png', 'wb') as f:
f.write(img)
#寫出文本
with open('./百度熱搜/熱搜文本.txt', 'a') as f:
f.write('\n'+'標題:' + str(title) + '\n' + '熱度:' + str(hot) + '\n' + '簡介:' + str(conent) + '\n' + '新聞鏈接:' + str(newUrl) + '\n\n')
except:
continue;
print('寫出成功!')
Hot_search()
5.2 爬取圖片壁紙
注意:這裡沒有自動創建保存文件的文件夾,自行修改
import requests
from bs4 import BeautifulSoup
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40"
}
def indexUrl():
indexUrls = ['//www.netbian.com/meinv/index.htm']
for i in range(2,4):
indexUrls.append('//www.netbian.com/meinv/index_'+str(i)+'.htm')
#保存圖片鏈接
imgUrls=[]
#當作圖片名字
imgName=1;
for i in indexUrls:
html=requests.get(url=i,headers=headers).content.decode('gbk')
soup=BeautifulSoup(html,'html.parser')
Alable=soup.find('div',class_='list').find_all('a')
# print(Alable)
for i in Alable:
#獲取圖片地址的後半段地址
iUrlP=i.attrs.get('href')
#去除無效地址
if 'http' in iUrlP:
continue;
#將殘缺的圖片頁面地址拼起來,形成完整圖片頁面地址
imgUrlP= '//www.netbian.com' + iUrlP
#向圖片網頁發起請求
imgPage=requests.get(url=imgUrlP,headers=headers).content.decode('gbk')
#將請求回來的源碼轉換為bs4
soup=BeautifulSoup(imgPage,'html.parser')
#獲取圖片鏈接地址
imgUrl=soup.find_all('div',class_='pic')[0].find('img').attrs.get('src')
#將圖片地址保存到列表中(可以不存)
imgUrls.append(imgUrl)
#向圖片地址發起請求
imgget=requests.get(url=imgUrl,headers=headers).content;
#下載圖片
with open('./壁紙/'+str(imgName)+'.jpg','wb') as f:
f.write(imgget)
imgName+=1;
print('下載成功')
indexUrl()
5.3 豆瓣電影 Top 250
結果保存到excel中的
import requests;
from bs4 import BeautifulSoup
import xlwt
# //movie.douban.com/top250?start=25&filter=
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42'}
#獲取翻頁頁面連接
def top250Urls():
purls=[]
urls=[]
for i in range(0,25,25):
url = '//movie.douban.com/top250?start='+str(i)+'&filter='
purls.append(url)
for purl in purls:
html=requests.get(url=purl,headers=headers).content.decode('utf-8')
soup=BeautifulSoup(html,'html.parser')
movie_div = soup.find_all('div', class_='item')
for movie in movie_div:
movieUrl = movie.find_all("div", class_="pic")[0]
movieUrl=movieUrl.find('a')
movieUrl=movieUrl.attrs.get('href')
urls.append(movieUrl)
return urls,
def Top250():
moviesTop=[]
urls=top250Urls()[0]
for url in urls:
html=requests.get(url=url,headers=headers).content.decode('utf-8')
soup=BeautifulSoup(html,"html.parser")
title=soup.find_all('span',property="v:itemreviewed")[0].text;
move_info=soup.find_all('div',id="info")[0]
performer=move_info.find_all('a',rel="v:starring")
actors=[]
for per in performer:
actors.append(per.text)
typeSpan=move_info.find_all('span',property="v:genre")
types=[]
for type in typeSpan:
types.append(type.text)
content = soup.find_all('span', property="v:summary")[0].text.strip('\n')
movies={
'title': title,
'performer': actors,
'type': types,
'content': content
}
moviesTop.append(movies)
WriteExcle(moviesTop)
# return moviesTop;
def WriteExcle(movies):
try:
#1、創建Workbook對象,就是創建Excel文件
work_boot=xlwt.Workbook(encoding='utf-8');
#2、創建sheet表單
sheet=work_boot.add_sheet('formName') #formName為表單名稱
#3、寫入Excel表頭
header=['電影名','演員','類型','電影簡介'];
for i in range(len(header)):
sheet.write(0,i,header[i]); #write(行,列,內容)
#寫入Excel內容
for i in range(len(movies)):
sheet.write(i+1,0,movies[i]['title'])
sheet.write(i+1, 1, movies[i]['performer'])
sheet.write(i+1, 2, movies[i]['type'])
sheet.write(i+1, 3, movies[i]['content'])
#保存文件
work_boot.save("小電影.xls")
print('寫入成功!')
except:
print('寫入失敗!')
Top250()
求求點贊、評論、收藏呀~