這篇文章咱們將使用 requests 和 xpath 爬取豆瓣電影 Top250,下面先貼上最終的效果圖:html
咱們首先使用 Chrome 瀏覽器打開 豆瓣電影 Top250,很容易能夠判斷出網站是一個靜態網頁python
而後咱們分析網站的 URL 規律,以便於經過構造 URL 獲取網站中全部網頁的內容json
首頁:https://movie.douban.com/top250瀏覽器
第二頁:https://movie.douban.com/top250?start=25&filter=網絡
第三頁:https://movie.douban.com/top250?start=50&filter=dom
...工具
不難發現,URL 能夠泛化爲 https://movie.douban.com/top250?start={page}&filter=,其中,page 表明頁數網站
最後咱們還須要驗證一下首頁的 URL 是否也知足規律,通過驗證,很容易能夠發現首頁的 URL 也知足上面的規律編碼
核心代碼以下:url
import requests # 獲取網頁源代碼 def get_page(url): # 構造請求頭部 headers = { 'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } # 發送請求,得到響應 response = requests.get(url=url,headers=headers) # 得到網頁源代碼 html = response.text # 返回網頁源代碼 return html
接下來咱們開始分析每個網頁的內容,並從中提取出須要的數據
使用快捷鍵 Ctrl+Shift+I
打開開發者工具,選中 Elements
選項欄分析網頁的源代碼
須要提取的數據包括(能夠使用 xpath 進行匹配):
html.xpath('//div[@class="hd"]/a/@href')
html.xpath('//div[@class="hd"]/a/span[1]/text()')
html.xpath('//div[@class="bd"]/p[1]//text()')
html.xpath('//div[@class="bd"]/div/span[2]/text()')
html.xpath('//div[@class="bd"]/div/span[4]/text()')
核心代碼以下:
from lxml import etree # 解析網頁源代碼 def parse_page(html): # 構造 _Element 對象 html_elem = etree.HTML(html) # 詳細連接 links = html_elem.xpath('//div[@class="hd"]/a/@href') # 電影名稱 titles = html_elem.xpath('//div[@class="hd"]/a/span[1]/text()') # 電影信息(導演/主演、上映年份/國家/分類) infos = html_elem.xpath('//div[@class="bd"]/p[1]//text()') roles = [j for i,j in enumerate(infos) if i % 2 == 0] descritions = [j for i,j in enumerate(infos) if i % 2 != 0] # 豆瓣評分 stars = html_elem.xpath('//div[@class="bd"]/div/span[2]/text()') # 評論人數 comments = html_elem.xpath('//div[@class="bd"]/div/span[4]/text()') # 得到結果 data = zip(links,titles,roles,descritions,stars,comments) # 返回結果 return data
下面將數據分別保存爲 txt 文件、json 文件和 csv 文件
import json import csv # 打開文件 def openfile(fm): fd = None if fm == 'txt': fd = open('douban.txt','w',encoding='utf-8') elif fm == 'json': fd = open('douban.json','w',encoding='utf-8') elif fm == 'csv': fd = open('douban.csv','w',encoding='utf-8',newline='') return fd # 將數據保存到文件 def save2file(fm,fd,data): if fm == 'txt': for item in data: fd.write('----------------------------------------\n') fd.write('link:' + str(item[0]) + '\n') fd.write('title:' + str(item[1]) + '\n') fd.write('role:' + str(item[2]) + '\n') fd.write('descrition:' + str(item[3]) + '\n') fd.write('star:' + str(item[4]) + '\n') fd.write('comment:' + str(item[5]) + '\n') if fm == 'json': temp = ('link','title','role','descrition','star','comment') for item in data: json.dump(dict(zip(temp,item)),fd,ensure_ascii=False) if fm == 'csv': writer = csv.writer(fd) for item in data: writer.writerow(item)
下面是完整代碼,也是幾十行能夠寫完
import requests from lxml import etree import json import csv import time import random # 獲取網頁源代碼 def get_page(url): headers = { 'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } response = requests.get(url=url,headers=headers) html = response.text return html # 解析網頁源代碼 def parse_page(html): html_elem = etree.HTML(html) links = html_elem.xpath('//div[@class="hd"]/a/@href') titles = html_elem.xpath('//div[@class="hd"]/a/span[1]/text()') infos = html_elem.xpath('//div[@class="bd"]/p[1]//text()') roles = [j.strip() for i,j in enumerate(infos) if i % 2 == 0] descritions = [j.strip() for i,j in enumerate(infos) if i % 2 != 0] stars = html_elem.xpath('//div[@class="bd"]/div/span[2]/text()') comments = html_elem.xpath('//div[@class="bd"]/div/span[4]/text()') data = zip(links,titles,roles,descritions,stars,comments) return data # 打開文件 def openfile(fm): fd = None if fm == 'txt': fd = open('douban.txt','w',encoding='utf-8') elif fm == 'json': fd = open('douban.json','w',encoding='utf-8') elif fm == 'csv': fd = open('douban.csv','w',encoding='utf-8',newline='') return fd # 將數據保存到文件 def save2file(fm,fd,data): if fm == 'txt': for item in data: fd.write('----------------------------------------\n') fd.write('link:' + str(item[0]) + '\n') fd.write('title:' + str(item[1]) + '\n') fd.write('role:' + str(item[2]) + '\n') fd.write('descrition:' + str(item[3]) + '\n') fd.write('star:' + str(item[4]) + '\n') fd.write('comment:' + str(item[5]) + '\n') if fm == 'json': temp = ('link','title','role','descrition','star','comment') for item in data: json.dump(dict(zip(temp,item)),fd,ensure_ascii=False) if fm == 'csv': writer = csv.writer(fd) for item in data: writer.writerow(item) # 開始爬取網頁 def crawl(): url = 'https://movie.douban.com/top250?start={page}&filter=' fm = input('請輸入文件保存格式(txt、json、csv):') while fm!='txt' and fm!='json' and fm!='csv': fm = input('輸入錯誤,請從新輸入文件保存格式(txt、json、csv):') fd = openfile(fm) print('開始爬取') for page in range(0,250,25): print('正在爬取第 ' + str(page+1) + ' 頁至第 ' + str(page+25) + ' 頁......') html = get_page(url.format(page=str(page))) data = parse_page(html) save2file(fm,fd,data) time.sleep(random.random()) fd.close() print('結束爬取') if __name__ == '__main__': crawl()
【爬蟲系列相關文章】