[Python從零到壹] 七.網絡爬蟲之Requests爬取豆瓣電影TOP250及CSV存儲 | 【生長吧!Python】(python從0到1)
https://blog.csdn.net/Eastmount
https://github.com/eastmountyxz/Python-zero2one
python爬蟲之爬取豆瓣電影top250實戰教學
文章目錄
一.requests基本用法
二.豆瓣網頁DOM樹分析
1.網頁源碼分析
2.網頁結構分析(翻頁)
三.Requests請求服務器
1.導入包
2.設置瀏覽器代理
3.請求服務器格式
4.請求服務器代碼匯總
四.xpath提取信息
1.獲取xpath節點方法
2.xpath提取文本
3.xpath提取鏈接
4.xpath提取標簽元素
五.正則表達式匹配信息
1.提取固定位置信息
2.匹配數字
六.CSV文件操作
1.CSV文件寫
2.CSV文件讀
七.完整代碼
1.提取本頁所有信息
2.最終代碼
八.總結
最后推薦大家關注我學生CSDN的博客,十分懷戀給他們上課的情形,博客也寫得不錯,寫作風格和我也很像,哈哈~ 學生楊友問我
“他現在不編程該行了,覺得遺憾嗎?”
我的回答是
“有點遺憾,但只要是我學生的選擇,自己喜歡,我都支持;也希望他們積極的去做,把每一件事做好做深,如有需要定會幫助,一起加油!”
https://blog.csdn.net/ayouleyang
前文賞析:
[Python從零到壹] 一.為什么我們要學Python及基礎語法詳解
[Python從零到壹] 二.語法基礎之條件語句、循環語句和函數
[Python從零到壹] 三.語法基礎之文件操作、CSV文件讀寫及面向對象
[Python從零到壹] 四.網絡爬蟲之入門基礎及正則表達式抓取博客案例
[Python從零到壹] 五.網絡爬蟲之BeautifulSoup基礎語法萬字詳解
[Python從零到壹] 六.網絡爬蟲之BeautifulSoup爬取豆瓣TOP250電影詳解
[Python從零到壹] 七.網絡爬蟲之Requests爬取豆瓣電影TOP250及CSV存儲
一.requests基本用法
requests模塊是用Python語言編寫的、基于urllib的第三方庫,采用Apache2 Licensed開源協議的http庫。它比urllib更方便簡潔,既可以節約大量的工作,又完全滿足http測試需求。requests是一個很實用的Python庫,編寫爬蟲和測試服務器響應數據時經常會用到,使用requests可以輕而易舉的完成瀏覽器相關操作。功能包括:
支持HTTP連接保持和連接池
支持使用cookie保持會話
支持文件上傳
支持自動響應內容的編碼
支持國際化的URL和POST數據自動編碼
推薦大家從requests官方網站進行學習,這里只做簡單介紹。官方文檔地址:
http://docs.python-requests.org/en/master/
假設讀者已經使用“pip install requests”安裝了requests模塊,下面講解該模塊的基本用法。
1.導入requests模塊
使用語句如下:
import requests
2.發送請求
requests模塊可以發送http常用的兩種請求:GET請求和POST請求。其中GET請求可以采用url參數傳遞數據,它是從服務器上獲取數據;而POST請求是向服務器傳遞數據,該方法更為安全,更多用法請讀者下來學習。
下面給出使用GET請求和POST請求獲取某個網頁的方法,得到一個命名為r的Response對象,通過這個對象獲取我們所需的信息。
import requests r = requests.get('https://github.com/timeline.json') r = requests.post("http://httpbin.org/post")
其他方法如下:
requests.put("http://httpbin.org/put") requests.delete("http://httpbin.org/delete") requests.head("http://httpbin.org/get") requests.options("http://httpbin.org/get")
3.傳遞參數
url通常會傳遞某種數據,這種數據采用鍵值對的參數形式置于url中,比如:
http://www.eastmountyxz.com/index.php?key=value
import requests payload = {'key1':'value1', 'key2':'value2'} r = requests.get('http://httpbin.org/get', params=payload) print(r.url) print(r)
輸出結果如下圖所示:
4.響應內容
requests會自動解碼來自服務器的內容,并且大多數Unicode字符集都能被無縫地解碼。當請求發出后,Requests會基于HTTP頭部對響應的編碼作出有根據的推測。
使用語句如下:
import requests r = requests.get('https://github.com/timeline.json') print(r.text)
輸出結果如下圖所示:
常用響應內容包括:
r.encoding
獲取當前的編碼
r.encoding = ‘utf-8’
設置編碼
r.text
以encoding解析返回內容。字符串方式的響應體,會自動根據響應頭部的字符編碼進行解碼
r.content
以字節形式(二進制)返回。字節方式的響應體,會自動為你解碼gzip和deflate壓縮
r.headers
以字典對象存儲服務器響應頭,但是這個字典比較特殊,字典鍵不區分大小寫,若鍵不存在則返回None
r.status_code
響應狀態碼
r.raw
返回原始響應體,也就是urllib的response對象,使用r.raw.read()
r.ok
查看r.ok的布爾值便可以知道是否登陸成功
r.json()
Requests中內置的JSON解碼器,以json形式返回,前提返回的內容確保是json格式的,不然解析出錯會拋異常
r.raise_for_status()
失敗請求(非200響應)拋出異常
post發送json請求:
import requests import json r = requests.post('https://api.github.com/some/endpoint', data=json.dumps({'some': 'data'})) print(r.json())
5.定制請求頭
如果你想為請求添加http頭部,只要簡單地傳遞一個字典(dict)給消息頭headers參數即可。例如,我們給github網站指定一個消息頭,則語句如下:
import requests data = {'some': 'data'} headers = {'content-type': 'application/json', 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'} r = requests.post('https://api.github.com/some/endpoint', data=data, headers=headers) print(r.text)
輸出結果如下圖所示:
6.獲取狀態碼和Cookies
r.headers
返回字典類型,頭信息
r.requests.headers
返回發送到服務器的頭信息
r.status_code
響應狀態碼
r.cookies
返回cookie
r.history
返回重定向信息,可以在請求是加上 allow_redirects = false 阻止重定向
具體示例如下:
import requests #獲取返回狀態 r = requests.get('https://github.com/Ranxf') print(r.status_code) print(r.headers) print(r.cookies) #打印解碼后的返回數據 r1 = requests.get(url='http://dict.baidu.com/s', params={'wd': 'python'}) print(r1.url) print(r1.text)
輸出結果如下圖所示:
同時響應狀態碼可以結合異常處理,如下:
import requests URL = 'http://ip.taobao.com/service/getIpInfo.php' # 淘寶IP地址庫API try: r = requests.get(URL, params={'ip': '8.8.8.8'}, timeout=1) r.raise_for_status() # 如果響應狀態碼不是 200,就主動拋出異常 except requests.RequestException as e: print(e) else: result = r.json() print(type(result), result, sep='\n')
7.超時設置
設置秒數超時,僅對于鏈接有效。
r = requests.get('url',timeout=1)
8.代理設置
proxies = {'http':'ip1','https':'ip2' } requests.get('url',proxies=proxies)
本小節只是簡單介紹了requests模塊,推薦讀者下來結合案例和官方網站進行更深入的學習和操作。
二.豆瓣網頁DOM樹分析
1.網頁源碼分析
豆瓣(Douban)是一個社區網站,創立于2005年3月6日。該網站以書影音起家,提供關于書籍、電影、音樂等作品的信息,其作品描述和評論都是由用戶提供,是Web 2.0網站中具有特色的一個網站。
當我們拿到一個網頁的時候,第一步并不是去測試它能否能使用requests簡單請求到html,而是要去選擇合適的方法進行爬取該網頁,弄明白它數據的加載方式,才可以讓我們的事半功倍,選擇一個好的請求方法也可以提升我們爬蟲程序的效率。
本文主要介紹爬取豆瓣電影排名前250名的電影信息。地址為:
https://movie.douban.com/top250?format=text
右鍵審查元素顯示HTML源代碼,如下圖所示。
對應的HTML部分代碼如下:
2.網頁結構分析(翻頁)
網站翻頁是網絡爬蟲中至關重要的一環,我們進入豆瓣電影 Top 250,查看它的網頁結構。點擊 “下一頁” ,查看它的URL鏈接,會發現下面的規律:
第1頁URL:https://movie.douban.com/top250?start=0&filter= 第2頁URL:https://movie.douban.com/top250?start=25&filter= 第3頁URL:https://movie.douban.com/top250?start=50&filter= ... 第10頁URL:https://movie.douban.com/top250?start=225&filter=
它是存在一定規律的,top250?start=25表示獲取第2頁(序號為26到50號)的電影信息;top250?start=50表示獲取第3頁(序號為51到75號)的電影信息,依次類推。
方法一:
我們結合數學公式寫一個循環獲取完整的250部電影信息。核心代碼如下:
i = 0 while i<10: num = i*25 #每次顯示25部 URL序號按25增加 url = 'https://movie.douban.com/top250?start=' + str(num) + '&filter=' crawl(url) #爬蟲電影信息 i = i + 1
方法二:
需要寫一個for循環,生成從0到225的數字即可,從上面的鏈接可以看出來,它的間隔為25,for page in range(0, 226, 25) 必須要取超過停止數據225,因為255不包含在其中,25是它的公差,程序表示為:
接下來使用python的requests庫去代替瀏覽器請求網頁的服務器,返回HTML文件,提取并保存信息,再生成下一頁的鏈接,繼續上面請求服務器的操作爬取信息。
三.Requests請求服務器
在向服務器發出請求時,我們先選擇第一個鏈接來進行測試,完成本頁所有內容的獲取,然后再獲取所有頁面的信息。
1.導入包
如果沒有安轉?requests?, 可以使用pip直接安轉
步驟:win+r運行——>cmd——>pip install requests
2.設置瀏覽器代理
網頁點擊右鍵,打開檢查,選擇Network,All
刷新網頁,選擇第一個文件,雙擊,選擇headers
設置的瀏覽器代理必須為字典型,如:
headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' }
3.請求服務器格式
請求源代碼向服務器發出請求,200代表成功。如果在后面加上?.text?表示輸出文本內容。
url是用一個鏈接
headers是用來做瀏覽器代理的內容
requests.get(url = url, headers = headers)
4.請求服務器代碼匯總
這里以第一頁內容為例,核心代碼如下所示:
import requests #設置瀏覽器代理,它是一個字典 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' } url = 'https://movie.douban.com/top250?start=0&filter=' #向服務器發出請求 r = requests.get(url = url, headers = headers) print(r.text)
輸出結果如下圖所示:
四.xpath提取信息
1.獲取xpath節點方法
xpath是按照HTML標簽的方式進行定位的,谷歌瀏覽器自帶有xpath,可以直接復制過來使用,簡單方便,運行速度快。輸出結果為:
//*[@id=“content”]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]
我們使用xpath時,也必須先對網頁進行?lxml?庫中的?etree?解析,把它變為特有的樹狀形式,才能通過它進行節點定位。
from lxml import etree #導入解析庫 html_etree = etree.HTML(reponse) #樹狀結構解析
2.xpath提取文本
當我們提取標簽內的文本時,需要在復制到的xpath后面加上?/text()?,告訴它我們需要提取的內容是一個標簽呈現的數據,如《肖申克的救贖》。
肖申克的救贖
結合xpath所提取的文字代碼為:
# coding:utf-8 # By:Eastmount 2021-02-25 import requests from lxml import etree #設置瀏覽器代理,它是一個字典 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' } url = 'https://movie.douban.com/top250?start=0&filter=' #向服務器發出請求 r = requests.get(url = url, headers = headers).text #解析DOM樹結構 html_etree = etree.HTML(r) name = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]/text()') print ("這是數組形式:",name) print ("這是字符串形式:",name[0])
輸出結果如下所示:
這是數組形式: ['肖申克的救贖'] 這是字符串形式: 肖申克的救贖
3.xpath提取鏈接
每一個鏈接都是在標簽內的,通常放在?src=" "?或者?href=" "?之中,如
xpath為:
//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a
提取鏈接時,需要在復制到的xpath后面加上?/@href?, 指定提取鏈接。
movie_url = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/@href') print ("這是數組形式:",movie_url) print ("這是字符串形式:",movie_url[0])
輸出結果如下所示:
這是數組形式: ['https://movie.douban.com/subject/1292052/'] 這是字符串形式: https://movie.douban.com/subject/1292052/
4.xpath提取標簽元素
這個網頁中電影的星級沒有用幾顆星的文本表示,而是標簽表示的,如:
所以只需要取出?class=" "?中的內容就可以得到星級了,復制它的xpath,和提取鏈接的方法一樣,在后面加上?/@class?即可。
rating = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[1]/@class') print ("這是數組形式:",rating) print ("這是字符串形式:",rating[0])
輸出結果如下所示:
這是數組形式: ['rating5-t'] 這是字符串形式: rating5-t
五.正則表達式匹配信息
前面第四篇文章我們詳細介紹了正則表達式的內容,它常常會與網絡爬蟲和數據預處理結合起來,簡化我們的工作。這里需要把結果中的信息匹配出來,可以使用正在表達式,單獨提取自己需要的信息,如星級,它都是以?rating5-t?方式呈現的,但是我們只需要它數字5位置的部分,所以需要進行二次提取。
1.提取固定位置信息
正則表達式中可以使用?.*??來進行匹配信息,沒有加括號時可以去掉不一樣的信息,不需要提取出來,加括號?(.*?)?可以提取出括號內的內容,如:
import re test = "rating5-t" text = re.findall('rating(.*?)-t', test) print (text)
輸出結果為:
['5']
這里再舉一個簡單的例子:
2.匹配數字
比如評價數,我們xpath提取到的數據格式為: 1056830人評價 ,保存的時候只需要數字即可,現在把數字提取出來:
import re data = "1059232人評價" num = re.sub(r'\D', "", data) print("這里的數字是:", num)
輸出結果為:
這里的數字是: 1059232
六.CSV文件操作
我們在使用Python進行網絡爬蟲或數據分析時,通常會遇到CSV文件,類似于Excel表格。第三篇文章我們詳細介紹了CSV文件的操作,保存內容與把大象放進冰箱是一樣的,分別為打開冰箱,把大象裝進去,關閉冰箱。這里我們進行簡單說明。
1.CSV文件寫
基本流程如下:
導入CSV模塊
創建一個CSV文件對象
寫入CSV文件
關閉文件
# -*- coding: utf-8 -*- import csv c = open("test-01.csv", "w", encoding="utf8", newline='') #寫文件 writer = csv.writer(c) writer.writerow(['序號','姓名','年齡']) tlist = [] tlist.append("1") tlist.append("小明") tlist.append("10") writer.writerow(tlist) print(tlist,type(tlist)) del tlist[:] #清空 tlist.append("2") tlist.append("小紅") tlist.append("9") writer.writerow(tlist) print(tlist,type(tlist)) c.close()
輸出結果如下圖所示:
2.CSV文件讀
基本流程如下:
導入CSV模塊
創建一個CSV文件對象
讀取CSV文件
關閉文件
# -*- coding: utf-8 -*- import csv c = open("test-01.csv", "r", encoding="utf8") #讀文件 reader = csv.reader(c) for line in reader: print(line[0],line[1],line[2]) c.close()
輸出結果如下圖所示:
在文件操作中編碼問題是最讓人頭疼的,尤其Python2的時候。但只需要環境編碼一致,注意相關轉換也能有效解決,而Python3文件讀寫操作寫清楚encoding編碼方式就能正常顯示。
七.完整代碼
1.提取本頁所有信息
通過前面的 xpath 只能提取到一條信息,如果我們要提取所有的信息,寫一個 for 循環把它遍歷出來即可。先復制幾個電影名字的 xpath,如前三個的:
li?標簽前的作為父級,后面的為子集,./?代替父級的位置,改寫為:
li = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li') for item in li: name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0] print (name)
此時的代碼如下所示:
# coding:utf-8 # By:Eastmount & ayouleyang 2021-02-25 import requests from lxml import etree #設置瀏覽器代理,它是一個字典 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' } url = 'https://movie.douban.com/top250?start=0&filter=' #向服務器發出請求 r = requests.get(url = url, headers = headers).text #解析DOM樹結構 html_etree = etree.HTML(r) name = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]/text()') print ("這是數組形式:",name) print ("這是字符串形式:",name[0]) #提取鏈接 movie_url = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/@href') print ("這是數組形式:",movie_url) print ("這是字符串形式:",movie_url[0]) #提取打分 rating = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[1]/@class') print ("這是數組形式:",rating) print ("這是字符串形式:",rating[0]) #提取本頁所有電影名 li = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li') for item in li: name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0] print (name)
輸出結果如下圖所示:
2.最終代碼
最終代碼如下所示:
# coding:utf-8 # By:Eastmount & ayouleyang 2021-02-25 import requests from lxml import etree import csv, re #設置瀏覽器代理,它是一個字典 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' } #創建文件夾并打開 fp = open("./豆瓣top250.csv", 'a', newline='', encoding = 'utf-8-sig') writer = csv.writer(fp) #寫入 writer.writerow(('排名', '名稱', '鏈接', '星級', '評分', '評價人數')) #循環遍歷TOP250的URL for page in range(0, 226, 25): #226 print ("正在獲取第%s頁"%page) url = 'https://movie.douban.com/top250?start=%s&filter='%page #請求源代碼 reponse = requests.get(url = url, headers = headers).text #解析DOM樹結構 html_etree = etree.HTML(reponse) #定位節點 注意迭代xpath應用 li = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li') for item in li: #排名 rank = item.xpath('./div/div[1]/em/text()')[0] #電影名稱 name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0] #鏈接 dy_url = item.xpath('./div/div[2]/div[1]/a/@href')[0] #評分 正則表達式提取 rating = item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0] rating = re.findall('rating(.*?)-t', rating)[0] if len(rating) == 2: star = int(rating) / 10 #int()轉化為數字 else: star = rating #評價人數 rating_num = item.xpath('./div/div[2]/div[2]/div/span[2]/text()')[0] content = item.xpath('./div/div[2]/div[2]/div/span[4]/text()')[0] content = re.sub(r'\D', "", content) #print (rank, name, dy_url, star, rating_num, content) #寫入內容 writer.writerow((rank, name, dy_url, star, rating_num, content)) fp.close()
運行結果如下圖所示:
最終保存的文件如下圖所示:
八.總結
該系列所有代碼-:
https://github.com/eastmountyxz/Python-zero2one
2020年在github的綠瓷磚終于貼完了第一年提交2100余次,獲得1500多+stars,開源93個倉庫,300個粉絲。挺開心的,希望自己能堅持在github打卡五年,督促自己不斷前行。簡單總結下,最滿意的資源是YQ爆發時,去年2月分享的輿情分析和情感分析,用這系列有溫度的代碼為武漢加油;最高贊的是Python圖像識別系列,也獲得了第一位來自國外開發者的貢獻補充;最花時間的是Wannacry逆向系列,花了我兩月逆向分析,幾乎成為了全網最詳細的該蠕蟲分析;還有AI系列、知識圖譜實戰、CVE復現、APT報告等等。當然也存在很多不足之處,希望來年分享更高質量的資源,也希望能將安全和AI頂會論文系列總結進來,真誠的希望它們能幫助到大家,感恩有你,一起加油~
希望能與大家一起在華為云社區共同承載,原文地址:https://blog.csdn.net/Eastmount/article/details/108887652
【生長吧!Python】有獎征文火熱進行中:https://bbs.huaweicloud.com/blogs/278897
(By:娜璋之家 Eastmount 2021-07-07 夜于武漢?)
參考文獻如下:
python爬蟲之爬取豆瓣電影top250實戰教學 - 楊友
北京豆網科技有限公司——豆瓣
https://2.python-requests.org/en/master/
Python—requests模塊詳解 - lanyinhao
Python 網絡
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。