本節通過一個具體的執行個體來看下編寫爬蟲的具體過程。以爬取豆瓣網 top250 電影的資訊為例,top250 電影的網址為:
https://movie.douban.com/top250
。在浏覽器的位址欄裡輸入
https://movie.douban.com/top250
,我們會看到如下内容:
對于每一部電影需要爬取的内容如下圖所示:
如上圖所示,爬取的内容包括電影排名、電影名稱、電影評分、電影屬于哪個國家、電影類型、電影的上映時間以及電影的導演、主演。了解了要爬取哪些内容之後,接下來需要知道這些内容對應的 html 内容。
知道了對應的 html 内容之後,接下來就是解析 html,擷取我們想要的内容。下面我們就逐漸介紹爬取的過程:
1.擷取 html
如上圖所示,由于每頁隻展示 25 個電影的資訊,要想擷取所有電影的資訊,需要通過一個循環來擷取全部 10 頁的内容。
1.1 導入所需的第三方庫
import requests
from bs4 import BeautifulSoup
import time
import
1.2 發送請求
1.2.1 設定 headers
由于豆瓣網會有反扒的機制,是以在請求網頁的時候,需要設定headers。headers 的内容如下:
headers = {
'User-Agent': ******,
'Cookie': ******
}
在實際運作時,需要将 ** 改成真實的 User-Agent 和 Cookie。
1.2.2 生成 url
第一頁的 url 為:
https://movie.douban.com/top250?start=0&filter=
。第二頁的 url 為:
https://movie.douban.com/top250?start=25&filter=
。第三頁的 url 為:
https://movie.douban.com/top250?start=50&filter=
。從上面三個 url 的組成可以看出,隻有 start 後面的數字在變,其他的都不變。我們可以根據這個規律來擷取所有的 url。
1.2.3 發送請求擷取響應
for i in range(10):
response = requests.get(
'https://movie.douban.com/top250?'+'start='+str(25*i)+'&filter=', headers=headers)
2.解析 html
2.1 響應解析
.text, 'lxml')
ol = soup.ol
all_li = ol.find_all('li')
for li in all_li:
rank = li.find('em', class_="").string
title = li.find('span', class_="title").string
rating = li.find('span', class_="rating_num").string
info = li.find('div', class_="bd").p.get_text().strip()
country = info.split('/')[-2]
genre = info.split('/')[-1]
release_time = info.split('\n')[1].split('/')[0].replace(" ", "")
director_actor = li.find('div', class_="bd").p.next_element.replace(
"\n", "").replace(" ", "")
ranks.append(rank)
titles.append(title)
ratings.append(rating)
countrys.append(country)
genres.append(genre)
release_times.append(release_time)
director_actors.append(director_actor)
由上面的 html 内容可以看到,每部電影的資訊處于
<li></li>
标簽内,而所有的
<li></li>
标簽又位于
<ol></ol>
标簽内。于是,首先擷取 ol 标簽的内容,然後再擷取所有的 li 标簽的内容。擷取到所有的 li 标簽之後,對每個 li 标簽進行周遊,擷取我們想要的内容。在所有的内容擷取完成後,将内容加入到相應的存儲清單中。
3.存儲内容
在擷取我們想要的内容之後,将内容存儲到 csv 檔案。代碼如下:
with open('top250.csv', 'w') as file:
writer = csv.writer(file, delimiter=',')
writer.writerow(["排名", "名稱", "評分", "國家", "類型", "上映時間", "導演&主演"])
for i in range(250):
writer.writerow([
ranks[i],
titles[i],
ratings[i],
countrys[i],
genres[i],
release_times[i],
director_actors[i]
])
4.完整代碼
綜合上面每一步的代碼之後,便可以得到完整的代碼:
import requests
from bs4 import BeautifulSoup
import time
import csv
headers = {
'User-Agent': ******,
'Cookie': ******
}
ranks = []
titles = []
ratings = []
inqs = []
countrys = []
genres = []
release_times = []
director_actors = []
for i in range(10):
response = requests.get(
'https://movie.douban.com/top250?'+'start='+str(25*i)+'&filter=', headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
ol = soup.ol
all_li = ol.find_all('li')
for li in all_li:
rank = li.find('em', class_="").string
title = li.find('span', class_="title").string
rating = li.find('span', class_="rating_num").string
info = li.find('div', class_="bd").p.get_text().strip()
country = info.split('/')[-2]
genre = info.split('/')[-1]
release_time = info.split('\n')[1].split('/')[0].replace(" ", "")
director_actor = li.find('div', class_="bd").p.next_element.replace(
"\n", "").replace(" ", "")
ranks.append(rank)
titles.append(title)
ratings.append(rating)
countrys.append(country)
genres.append(genre)
release_times.append(release_time)
director_actors.append(director_actor)
time.sleep(3)
with open('top250.csv', 'w') as file:
writer = csv.writer(file, delimiter=',')
writer.writerow(["排名", "名稱", "評分", "國家", "類型", "上映時間", "導演&主演"])
for i in range(250):
writer.writerow([
ranks[i],
titles[i],
ratings[i],
countrys[i],
genres[i],
release_times[i],
director_actors[i]
])