Python 豆瓣電影Top250爬取並生成csv文件
久違的博客更新,事出有因,晚上有朋友叫我幫忙爬取豆瓣電影Top250數據用來做分析,不過呢網上的這方面的文章有些不好使,我就自己重寫了,更新一下網絡上這個空缺。
雖然這次的爬取很容易,因爲這個網址是靜態網頁,直接網頁源碼就可以解析了,不過還是值得你一看,有些細小的點說不定你未曾見識過。
網頁鏈接是這個: https://movie.douban.com/top250
我們直接可以右鍵彈出菜單點“檢查元素”,可以直接找到需要的信息,這次我們的目的是要獲取每部電影的:
’電影排名’,‘電影名稱’,‘導演’,‘上映年份’,‘製片國家’,‘電影類型’,‘電影評分’,‘評價人數’,'電影短評’
開始代碼講解了:
import requests #每次都是你,最頻繁使用的庫
from lxml import etree """內含xpath,本人極力推薦使用xpath,不要用bs了"""
import re #正則是爲了一些文本的提取,等會你就知道了
如果你在 lxml 這裏報錯就要去安裝它了,cmd窗口裏輸入 pip install lxml 。
有時候可能會安裝失敗,大概率是網絡問題,多輸入幾次就好了。
我們先從程序開始的地方看起
if __name__ == '__main__':
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}
"""movieInfo將作爲csv文件的表頭,我們將把數據逐行加入這個列表,否則在保存時就不是我們想要的樣子了"""
movieInfo = [['電影排名','電影名稱','導演','上映年份','製片國家','電影類型','電影評分','評價人數','電影短評']]
for i in range(0,250,25):
url='https://movie.douban.com/top250?start={}'.format(i)
try:
"""因爲爬取靜態網頁沒有難度就直接一個函數搞定"""
DoubanSpider(movieInfo,url,headers=headers)
except:
break
"""將movieInfo保存爲csv格式"""
with open('movie.csv','w',encoding='utf-8')as f:
for info in movieInfo:
#逗號分隔每個列表元素然後寫入,然後回車到下一行
f.write(','.join(info)+'\n')
print('爬取結束')
重頭戲上場了,代碼寫的實在不敢恭維,因爲趕時間,就沒有什麼優化,請見諒
def DoubanSpider(movieInfo,url,headers):
response = requests.get(url,headers=headers)
html_ele = etree.HTML(response.text)
"""前面幾個都是可以直接xpath提取到的,後面就比較麻煩,
不瞭解的xpath的話可以學習一下,當真好用"""
rank = html_ele.xpath('//div[@class="item"]/div/em/text()')
film_name = html_ele.xpath('//div[@class="item"]/div/a/img/@alt')
quote = html_ele.xpath('//p[@class="quote"]/span/text()')
"""分析代碼的時候發現評分和評價人數是合在一起的"""
temp_content = html_ele.xpath('//div[@class="star"]/span/text()')
score=[]
people=[]
index=1
for i in temp_content:
if index%2==1: #奇數的是評分
score.append(i)
else: #偶數的是人數
people.append(i)
index+=1
"""全文最麻煩之處,剩餘的信息都糊在一片文本里"""
film_content = html_ele.xpath('//div[@class="bd"]/p/text()')
#用re匹配到數字字符,可是發現出來好多不用的零字符
#上映年份
film_year_temp = re.findall('\d+',str(film_content))
film_year=[]
for i in film_year_temp:
if i!='0':#過濾掉'0'
film_year.append(i)
#獲取導演名字
film_director = re.findall(r'導演:(.*?)主演',str(film_content))
director=[]
for i in film_director:
director.append(i.split(r' ')[1])#這裏只是讓信息輸出規範化
#這裏就是一連串的文本,然後被分成了好幾個小列表
country=[]
index=1
for i in film_content:
if index%4==2:
country.append(i.split('\xa0')[2])
index+=1
film_type=[]
index=1
for i in film_content:
if index%4==2:
film_type.append(i.split('\xa0')[4].strip())
index+=1
"""是時候展現真正的技術啦,hh"""
"""這裏的zip是把這些個列表都綁定在一起,爲了後面的循環可以每次同時取出每個列表的順序元素。"""
"""這麼做的原因是我們每次函數執行對應數據的列表就被擴充成25,不可能一次性塞給movieInfo,否則存爲csv結果就是事與願違,不信你可以自己試試。"""
"""當然你也可以改代碼,每次列表擴充一個,立即加入moiveInfo當中"""
nvs=zip(rank,film_name,director,film_year,country,film_type,score,people,quote)
for rank,film_name,film_director,film_year,country,film_type,score,people,quote in nvs:
movieInfo.append([rank,film_name,film_director,film_year,country,film_type,score,people,quote])
print(url,'爬取完畢')
大功告成,最後就是驗收啦!
在這個py文件同目錄下就會生成movie.csv文件,可以用記事本打開,不過excel打開纔是我們想要的。
當你用excel打開時。。。
What這是啥?原來是excel打開csv時亂碼問題,這裏你可以參考解決方案:
csv打開時亂碼解決方案
本人親測方法2有用,效果極佳:
終於完功了!!!
覺得有幫助就點個贊吧!