from bs4 import BeautifulSoup
import re # 正則表表達(dá)式文字匹配
import urllib.request, urllib.error # 指定url,獲取網(wǎng)頁數(shù)據(jù)
import xlwt
findlink = re.compile(r'a href="(.*?)">') # 電影鏈接
findImageSrc = re.compile(r'<img.*src="(.*?)"', re.S) # re.S讓換行符包含著其中 #圖片鏈接
findTitle = re.compile(r'<span class="title">(.*)</span>') # 標(biāo)題
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>') # 評分
findJudge = re.compile(r'<span>(\d*)人評價(jià)</span>') # 人數(shù)
findInq = re.compile(r'<span class="inq">(.*)</span>') # 概況
findBd = re.compile(r'<p class="">(.*?)</p>', re.S) # 相關(guān)信息
def main():
# 定義基礎(chǔ)URL,用于構(gòu)造完整的URL來請求數(shù)據(jù)
baseurl = "https://movie.douban.com/top250?start="
# 調(diào)用getdata函數(shù),傳入基礎(chǔ)URL,獲取數(shù)據(jù)并返回
datalist = getdata(baseurl)
# 打印獲取到的數(shù)據(jù)列表
print(datalist)
# 定義保存路徑,將數(shù)據(jù)保存到movies.xls文件中
savepath = ".\\movies.xls" # 保存路徑
# 調(diào)用saveData函數(shù),傳入獲取到的數(shù)據(jù)列表和保存路徑,保存數(shù)據(jù)
saveData(datalist, savepath)
# 定義函數(shù),用于發(fā)送HTTP請求并獲取返回的HTML內(nèi)容
def askURL(url):
# 定義字典,作為HTTP請求的頭部信息
head = {
"User-Agent": " Mozilla / 5.0(Linux;Android6.0;Nexus5 Build / MRA58N) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 99.0.4844.51Mobile Safari / 537.36"
}
# 根據(jù)給定的URL和頭部信息,構(gòu)造一個(gè)HTTP請求對象
request = urllib.request.Request(url, headers=head)
# 初始化一個(gè)空字符串,用于存儲(chǔ)HTML內(nèi)容
html = ""
try:
# 使用urllib.request的urlopen函數(shù),發(fā)送HTTP請求并獲取響應(yīng)對象
response = urllib.request.urlopen(request)
# 從響應(yīng)對象中讀取HTML內(nèi)容,并解碼為utf-8格式的字符串
html = response.read().decode('utf-8')
# 注釋:打印HTML內(nèi)容(實(shí)際代碼被注釋掉)
# print(html)
except urllib.error.URLError as e:
# 如果發(fā)生URL相關(guān)的錯(cuò)誤,處理異常
if hasattr(e, "code"):
# 打印異常中的錯(cuò)誤代碼
print(e.code)
if hasattr(e, "reason"):
# 打印異常中的錯(cuò)誤原因描述
print(e.reason)
return html # 返回獲取到的HTML內(nèi)容
# 爬取網(wǎng)頁
def getdata(baseurl):
# 初始化一個(gè)空的數(shù)據(jù)列表,用于存放解析出的數(shù)據(jù)
datalist = []
# 從基礎(chǔ)URL開始,循環(huán)請求10次,每次請求偏移25
for i in range(0, 10):
url = baseurl + str(i * 25) # 構(gòu)造完整的URL
html = askURL(url) # 發(fā)送HTTP請求并獲取HTML內(nèi)容
soup = BeautifulSoup(html, "html.parser") # 使用BeautifulSoup解析HTML內(nèi)容
# 遍歷解析出的每一個(gè)'div'標(biāo)簽,類名為"item"
for item in soup.find_all('div', class_="item"):
# 初始化一個(gè)空的數(shù)據(jù)列表,用于存放當(dāng)前item的數(shù)據(jù)
data = []
item = str(item) # 將item轉(zhuǎn)換為字符串,以便進(jìn)行正則表達(dá)式匹配
# 尋找鏈接
link = re.findall(findlink, item)[0] # 使用正則表達(dá)式匹配鏈接
data.append(link) # 將鏈接添加到數(shù)據(jù)列表中
# 尋找圖片源地址
image = re.findall(findImageSrc, item)[0] # 使用正則表達(dá)式匹配圖片源地址
data.append(image) # 將圖片源地址添加到數(shù)據(jù)列表中
# 尋找標(biāo)題
title = re.findall(findTitle, item) # 使用正則表達(dá)式匹配標(biāo)題
if (len(title) == 2): # 如果匹配到兩個(gè)標(biāo)題
ctitle = title[0] # 第一個(gè)標(biāo)題
data.append(ctitle) # 將第一個(gè)標(biāo)題添加到數(shù)據(jù)列表中
otitle = title[1].replace("/", "") # 第二個(gè)標(biāo)題,移除其中的"/"字符
data.append(otitle.strip()) # 將第二個(gè)標(biāo)題添加到數(shù)據(jù)列表中,并移除首尾的空格
else: # 如果只匹配到一個(gè)標(biāo)題
data.append(title[0]) # 將標(biāo)題添加到數(shù)據(jù)列表中
data.append(" ") # 添加一個(gè)空格,作為第二個(gè)標(biāo)題的占位符
# 尋找評分
rating = re.findall(findRating, item)[0] # 使用正則表達(dá)式匹配評分
data.append(rating) # 將評分添加到數(shù)據(jù)列表中
# 尋找評價(jià)人數(shù)
judgeNum = re.findall(findJudge, item)[0] # 使用正則表達(dá)式匹配評價(jià)人數(shù)
data.append(judgeNum) # 將評價(jià)人數(shù)添加到數(shù)據(jù)列表中
# 尋找描述或簡介
inq = re.findall(findInq, item) # 使用正則表達(dá)式匹配描述或簡介
if len(inq) != 0: # 如果匹配到了描述或簡介
inq = inq[0].replace("。", "") # 移除其中的"。"字符
data.append(inq) # 將描述或簡介添加到數(shù)據(jù)列表中
else: # 如果沒匹配到描述或簡介
data.append("") # 在數(shù)據(jù)列表中添加一個(gè)空字符串作為占位符
bd = re.findall(findBd, item)[0] # 使用正則表達(dá)式匹配導(dǎo)演或主演信息,這里可能存在錯(cuò)誤,導(dǎo)演和主演信息不在一起匹配,此處可能需要分別處理導(dǎo)演和主演的信息。
# 并且匹配結(jié)果也沒有處理雙引號(hào)的問題。導(dǎo)演和主演的信息可能需要分開處理。
bd = re.sub('<br(\s+)?/>(\s+)?', " ", bd) # 替換HTML中的換行標(biāo)簽為空格字符,這里可能需要考慮HTML轉(zhuǎn)義字符的問題。
# 并且這里只替換了一次,可能存在重復(fù)替換的問題。導(dǎo)演和主演的信息可能需要分別處理。
bd = re.sub('/', " ", bd) # 將"/"替換為空格字符,這里可能存在錯(cuò)誤,因?yàn)?/ "在正則表達(dá)式中被錯(cuò)誤地轉(zhuǎn)義了
# 3 保存數(shù)據(jù)
# 定義saveData的函數(shù),接收兩個(gè)參數(shù):datalist和savepath
def saveData(datalist, savepath):
# 打印"save...",表示開始保存數(shù)據(jù)
print("save...")
# 創(chuàng)建一個(gè)Excel工作簿,設(shè)置編碼為utf-8,樣式壓縮為0
book = xlwt.Workbook(encoding="utf-8", style_compression=0)
# 在工作簿中添加一個(gè)名為'movies'的工作表,設(shè)置cell_overwrite_ok為True,表示允許覆蓋單元格內(nèi)容
sheet = book.add_sheet('movies', cell_overwrite_ok=True)
# 定義一個(gè)包含列名的列表
col = ("Movies_link", "Image_link", "Chinese_name", "Foreign_name", "Rating", "Reviews", "概況", "Summary")
# 循環(huán)遍歷col中的每一個(gè)元素,從0到7,將元素寫入到工作表的第0行對應(yīng)列中
for i in range(0, 8):
sheet.write(0, i, col[i])
# 循環(huán)遍歷datalist中的每一個(gè)元素,從0到249
for i in range(0, 250):
# 打印當(dāng)前處理的條目序號(hào)
print("第%d條" % (i + 1))
# 從datalist中獲取第i個(gè)元素,賦值給data
data = datalist[i]
# 循環(huán)遍歷data中的每一個(gè)元素,從0到7,將元素寫入到工作表的第i+1行對應(yīng)列中
for j in range(0, 8):
sheet.write(i + 1, j, data[j])
# 將工作簿保存到指定的路徑下,文件名為savepath
book.save(savepath)
main()
print("爬取完畢!")
項(xiàng)目結(jié)構(gòu):
- 導(dǎo)入庫
- 正則表達(dá)式:用于匹配網(wǎng)頁中電影信息中的鏈接、圖片標(biāo)題等
- 主程序:調(diào)用get_data和save_data
- HTTP請求函數(shù):ask_URL
- 獲取電影數(shù)據(jù)函數(shù):get_data à 把信息保存data_list中
- 保存數(shù)據(jù)函數(shù):save_data
文章來源地址http://www.zghlxwxcb.cn/news/detail-819050.html
文章來源:http://www.zghlxwxcb.cn/news/detail-819050.html
到了這里,關(guān)于Python---爬蟲學(xué)習(xí)(詳細(xì)注釋/優(yōu)化)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!