回家之後就不想學習了…
這次用的是lxml庫,因為聽說比起BeautifulSoup它的速度更快,然後就想了解一下。(全部的代碼在最下面)
import庫
from lxml import etree
import requests
import json
# from time import sleep
這是要用到的庫。requests請求html,lxml解析html文檔,然後得到的資料通過json存儲在json檔案。
分析豆瓣網頁
第一頁:https://movie.douban.com/top250
第二頁:https://movie.douban.com/top250?start=25&filter=
第三頁:https://movie.douban.com/top250?start=50&filter=
發現一頁有25個電影介紹,每多一頁start=的數目遷移25。是以嘗試:
https://movie.douban.com/top250?start=0
發現成功後,分析網頁源代碼。
這次抓取的隻是電影名、排名、分數、和簡介。還是跟之前那樣子通過Chrome的審查元素抓取Xpath路徑。
分别有:
# info
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[1]/em index
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1] name
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[2] rate
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/p[2]/span quote
這是第一個電影的資訊,可以看出來我們要抓取的内容都在一個統一的節點
div
上。而每個電影都在不同的
li
裡面。
重點代碼
def get_one_page(url):
try:
response = requests.get(url)
if response.status_code == :
return response.content
return None
except requests.RequestException:
return None
這是通過
request
來請求一個頁面的函數。使用的
RequestException
是
request
庫自帶的,代表連接配接出錯。
status_code
等于200時代表連接配接正常,這時候我們傳回頁面。
更多狀态碼可以上菜鳥:http://www.runoob.com/http/http-status-codes.html
def parse_one_page(content):
html = etree.HTML(content)
films = html.xpath('//div[@class="article"]/ol/li')
for film in films:
yield{
'name': film.xpath('./div//span[@class="title"][1]/text()'),
'index': film.xpath('./div//div[@class="pic"]/em/text()'),
'quote': film.xpath('./div//span[@class="inq"]/text()'),
'rating_num': film.xpath('./div//span[@class="rating_num"]/text()'),
}
xpath用法中,//表示搜尋所有的子孫節點,而/是直接的子節點。我們先通過class屬性選擇對應的
div
,再選擇它分支的所有
li
節點。這個時候,我們再疊代所有的
li
節點。
需要注意的是,我們在疊代的時候隻操作目前節點,是以我們路徑都有個
./
最後選擇的是yield,這樣子這個函數就是個疊代器了。在主函數中,我們疊代這個函數收集資訊就可以了。
def write(data):
with open('douban_top250.json', 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
這裡把資訊寫到自己建的檔案
douban_top250.json
中。
if __name__ == '__main__':
douban_films = 'https://movie.douban.com/top250?start='
for i in range(, , ):
# print(i)
page = douban_films + str(i)
content = get_one_page(page)
if content is not None:
for item in parse_one_page(content):
# print(item)
write(item)
else:
print('Request Error')
# sleep(5)
這個是總的過程。自己設定
i
周遊25個頁面,然後通過自己構造的函數來解析資訊,最後輸入到檔案中。需要解釋的是,這裡注釋掉的三個語句是我在測試的時候檢查錯誤先寫上去的。
最終的代碼如下(好簡短):
from lxml import etree
import requests
import json
def get_one_page(url):
try:
response = requests.get(url)
if response.status_code == :
return response.content
return None
except requests.RequestException:
return None
def parse_one_page(content):
html = etree.HTML(content)
films = html.xpath('//div[@class="article"]/ol/li')
for film in films:
yield{
'name': film.xpath('./div//span[@class="title"][1]/text()'),
'index': film.xpath('./div//div[@class="pic"]/em/text()'),
'quote': film.xpath('./div//span[@class="inq"]/text()'),
'rating_num': film.xpath('./div//span[@class="rating_num"]/text()'),
}
def write(data):
with open('douban_top250.json', 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
if __name__ == '__main__':
douban_films = 'https://movie.douban.com/top250?start='
for i in range(, , ):
page = douban_films + str(i)
content = get_one_page(page)
if content is not None:
for item in parse_one_page(content):
write(item)
else:
print('Request Error')
效果如圖: