前言:哇,今天終于能訪問豆瓣了,前幾天爬太多次了,網頁都不讓我訪問了(要登錄)。
先來個小練習試試手吧!
爬取豆瓣第一頁(多頁同上篇文章)所有電影的排名、電影名稱、星級和評分,并用Excel存儲
網址是:豆瓣電影 Top 250? 大家先自己嘗試一下吧,還是簡單的,我就直接放代碼了
import requests
from bs4 import BeautifulSoup
import pandas as pd
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}
r=requests.get("https://movie.douban.com/top250",headers=headers)
if r.status_code!=200:raise Exception("error")
soup=BeautifulSoup(r.text,"html.parser")
datas=[['排名','電影名稱','星級','評分']]
articles=soup.find_all('div',class_='item')
for article in articles:rank=article.find('em').get_text()title=article.find('span',class_='title').get_text() #星級在class屬性里,get('class')返回的是列表,因為HTML的class屬性可以包含多個類名,因此BeautifulSoup將其存儲為一個列表star=article.find('div',class_='bd').find('span').get('class')[0].replace('rating','').replace('-t','') #string的replace方法,只保留數字score=article.find('span',class_='rating_num').get_text()datas.append([rank,title,star,score])
df=pd.DataFrame(datas)
df.to_excel('doubanTop25.xlsx')
easy吧,不過,值得提一下的是,網頁帶小數星級的表示不準確,4.5星級為45
可以觀察到star與score都在同一個div標簽下,所以還可以用這兩行代碼代替
data=article.find('div',class_='bd').find('div').find_all('span')
star,score=data[0]['class'][0],data[1].get_text() #這樣star就是一整個字符
?爬取動態加載的網頁
我們來試著爬取杭州今年5個月的天氣數據(最近都是下雨,有點不喜歡哦,小小的毛毛細雨我覺得還好,但是大暴雨真是什么都不方便)
我們選擇不同的月份,可以發現網頁的url都沒有發生改變,說明這個網頁不是靜態網頁,它是后臺異步加載的動態網頁,我們表面不能知道它實際的鏈接的,那么我們需要抓包來進行分析。
右鍵,點擊“檢查”,點擊“網絡”
不要直接點擊“重新加載頁面”,那會加載大量頁面彈出來一大堆。我們再次查詢一個月份信息,發現后臺會發送一個請求“GetHistoty……”(或者點擊Fecth/XHR這是發送異步請求的意思,里面就是我們要抓的包)
?點擊“請求”進去看一下,可以發現“請求URL”與網頁上方的url不是同一個,這個就是異步加載的,請求方式為“GET”。復制URL“?”前面的部分(后面是參數部分,都在負載里)為url
復制“請求標頭”里的User-Agent,設置為headers用于反爬
這個網站的反爬做的有點好啊,還需要設置headers的Referer屬性 ,也在請求標頭里面,復制下來
?點擊“負載”,前兩項是杭州地區有關的編碼,都是不會變的,下面兩項就是查詢的year與month。復制里面的內容為請求的參數(設為字典類型)
點擊“響應”,看一下返回的結果是怎樣的
可以看到響應是json類型的數據(JSON (JavaScript Object Notation)數據由鍵值對組成,類似于字典,是一種輕量級的數據交換格式)?
點擊“預覽”,可以看到格式化的展示,將鼠標移到data的值可以看到html的數據(截圖沒法展示,自行看),可以發現里面有個<table>標簽?
“響應”里也能看到,不過“預覽”可視化更好?
表格數據用pandas可以很容易地解析?
import requests
import pandas as pd
from io import StringIO
url='https://tianqi.2345.com/Pc/GetHistory'
headers={"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0','Referer':'https://tianqi.2345.com/wea_history/58457.htm'}
params={
"areaInfo[areaId]":58457,
"areaInfo[areaType]":2,
"date[year]":2025,
"date[month]":4
}
r=requests.get(url,headers=headers,params=params) #請求頭和參數都為字典類型
if r.status_code!=200:raise Exception('error')
data=r.json()["data"] #r.json()方法會將返回的JSON格式的響應解析為一個Python對象(一般為字典/列表),我們取出‘data’鍵的值(是字符串)
data=StringIO(data) #使用StringIO對象來包裝HTML字符串,可以將字符串視為文件來讀取
df=pd.read_html(data)[0] #pd.read_html()方法可以解析一個網頁中所有的表格,返回一個列表,里面的元素是DataFrame的數據結構
print(df)
這樣我們單個的網頁就爬取成功了,輸出如下
?我們現在來爬取1-5月的數據,根據前面的分析,只需要將參數改一下就可以了
import requests
import pandas as pd
from io import StringIO
url='https://tianqi.2345.com/Pc/GetHistory'
headers={"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0','Referer':'https://tianqi.2345.com/wea_history/58457.htm'}
def craw_weather(month):params={"areaInfo[areaId]":58457,"areaInfo[areaType]":2,"date[year]":2025,"date[month]":month}r=requests.get(url,headers=headers,params=params) if r.status_code!=200:raise Exception('error')data=r.json()["data"]data=StringIO(data) df=pd.read_html(data)[0] return df
lst=[] #里面是每個月的df數據
for n in range(1,6):df=craw_weather(n)lst.append(df)
datas=pd.concat(lst) #pd.concat()方法用于將多個Pandas對象(DataFrame或Series)沿著特定軸連接起來,非常靈活,可以用于行連接、列連接等多種操作
datas.to_excel('杭州1-5月天氣數據.xlsx',index=False) #Pandas在將df保存為Excel時,會將df的索引作為單獨的一列寫入文件,設置index=False可以不包含索引列
展示如下,昨天的數據都有了
批量爬取正本小說
整本小說稍微有點多了,我們就拿番茄小說的top1為例吧,爬取前10章的內容,先批量爬取每一章的鏈接和章節名稱,再根據鏈接爬取正文,最后將文章寫到文件中去
網頁地址為十日終焉完整版在線免費閱讀_十日終焉小說_番茄小說官網
直接檢索元素哈,可以發現所有章節都在特定的<div>標簽下
文章內容也在特定<div>標簽下
代碼如下
import requests
from bs4 import BeautifulSoup
def get_urls():root_url='https://fanqienovel.com/page/7143038691944959011'r=requests.get(root_url)if r.status_code!=200:raise Exception('error')soup=BeautifulSoup(r.text,"html.parser")datas=[]n=0for chapter in soup.find('div',class_='chapter').find_all('a'):if n==10:breakdatas.append(['https://fanqienovel.com'+chapter['href'],chapter.get_text()])n+=1return datas
def get_chapter(url):r=requests.get(url)if r.status_code!=200:raise Exception('error')soup=BeautifulSoup(r.text,"html.parser")content=soup.find('div',"muye-reader-content noselect").get_text()return content
for urls in get_urls():url,title=urlswith open(f'{title}.txt','w',encoding='utf-8') as ch: #寫入文件ch.write(get_chapter(url))
展示如下
最后文章字符是亂碼,因為網頁源代碼就是亂碼的,查看<head>標簽里的charset,編碼就是‘utf-8’每錯,主包也嘗試了幾種方法還是不能正常顯示,可能瀏覽器可能會對顯示的內容進行一些渲染或轉換,我們講到后面再來嘗試
那爬這個有什么用呢??有些盜版網站不是小廣告很多嘛,那你就可以把文章爬下來看咯~