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()

求求點贊、評論、收藏呀~