零基础爬虫requests初阶教程,手把手教你爬数据
目錄
一、環境與工具
二、學爬蟲必備知識
三、簡單體驗 requests
四、get 請求
3.1 基礎講解一
3.3 基礎講解二
3.2 基礎講解三
3.5 獲取請求頭
3.6 添加請求頭
3.5 知乎爬取+反扒技術
3.6 抓取二進制數據
3.7 美女私房照爬取( 準備發車)
四、 POST 請求
4.1 數據表單提交
4.2 添加請求頭
4.3 提交json
4.4 普通文件上傳
一、環境與工具
環境:jupyter
如果你沒有安裝該工具和不會使用,請看這一篇文章:pycharm安裝配置與使用詳細教程
你可能還會需要這兩篇文章:
1-親測jupyter打不開瀏覽器
2-設置默認打開文件夾
模塊安裝:
演示安裝:
?安裝完畢:
二、學爬蟲必備知識
如果你python基礎都不會,建議你先大佬寫的python基礎專欄:python全棧基礎教程
他的基礎專欄包括最基本的基礎,re正則表達式,畫圖,文件處理,django,mysql操作處理等,如果你基礎都不會,建議你先收藏本篇內容,去學完基礎,再來看本篇文章。
三、簡單體驗 requests
以百度為例子:
網址:https://www.baidu.com/
import requests r = requests.get('https://www.baidu.com/') print(type(r)) print(r.status_code) print(type(r.text)) print(r.text) print(r.cookies)運行結果:
輸出結果得到了一個 Response 對象,然后分別輸出了 Response 的類型、狀態碼、響應體的類型、內容以及 Cookies。或許在這里你還看不懂,那么請看下去,你會懂的!
四、get 請求
3.1 基礎講解一
還是以百度為例子:
網址:https://www.baidu.com/
為什么我這里只演示了百度?因為這個不會被反扒,如果被反扒,則會返回為空。大家可以試試別的網址,比如我的博客地址,基本返回為空。但不必擔心,后續會學習并分享給大家有關反扒的。
我們用get請求網址,打印txt則獲取到百度頁面源碼:
import requests r = requests.get('https://www.baidu.com/') print(r.text)輸出結果:
3.3 基礎講解二
我們以CSDN為例:
這里就直接使用requests模塊的get函數直接來獲取(get和urlopen是相同的),主要是這個更方便些:
import requestsr=requests.get('https://mp.csdn.net/mp_blog/manage/article')print(r.status_code)#打印狀態碼 print(r.text)#打印文本 print(r.cookies)#打印cookie運行結果:
?再舉例子:
import requestsr=requests.post('https://www.csdn.net/?spm=1011.2124.3001.5359') s=requests.put('https://www.csdn.net/?spm=1011.2124.3001.5359')print(r.status_code) print(r.text) print(s.status_code) print(s.text)運行結果:
?雖然請求失敗但不影響,主要是介紹下用requests模塊的話,可以很簡單的方式請求,比如說put,post,delete這些之間換一下就換了一個請求方法。這里之所以請求失敗是因為我們被反扒了。?
3.2 基礎講解三
首先,構建一個最簡單的 GET 請求,請求的鏈接為 http://httpbin.org/get,該網站會判斷如果客戶端發起的是 GET 請求的話,它返回相應的請求信息.
代碼:
運行結果:
?此時我們可以發現,我們成功發起了 GET 請求,返回結果中包含請求頭、URL、IP 等信息。
那么,對于 GET 請求,如果要附加額外的信息,一般怎樣添加呢?比如現在想添加兩個參數,其中 name 是 germey,age 是 22。
要構造這個請求鏈接,是不是要直接寫成:
r = requests.get('http://httpbin.org/get?name=germey&age=22')這同樣很簡單,利用 params 這個參數就好了,示例如下:
import requests data = { 'name': 'germey', 'age': 22 } r = requests.get("http://httpbin.org/get", params=data) print(r.text)運行結果:
?通過返回信息我們可以判斷,請求的鏈接自動被構造成了:http://httpbin.org/get?age=22&name=germey
另外,網頁的返回類型實際上是 str 類型,但是它很特殊,是 JSON 格式的。所以,如果想直接解析返回結果,得到一個字典格式的話,可以直接調用 json 方法。
示例如下:
import requests r = requests.get("http://httpbin.org/get") print(type(r.text)) print(r.json()) print(type(r.json()))運行結果:
?我們可以發現,調用 json 方法,就可以將返回結果是 JSON 格式的字符串轉化為字典。
3.4 獲取cookie
import requestsheaders={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36' }#請求頭url='https://www.csdn.net/?spm=1011.2124.3001.5359'r=requests.get(url=url,headers=headers)print(r.cookies)#直接打印運行結果:
3.5 獲取請求頭
手動獲取:
點擊右鍵,選擇檢查,再選擇network,刷新一下(ctrl+r),隨機選其中一個內容,(或如圖)如下將 User-Agent 后的內容復制出來就行:
3.6 添加請求頭
我們也可以通過 headers 參數來傳遞頭信息。比如,在下面我們的面 “知乎” 的例子中,如果不傳遞 headers,就不能正常請求,請求結果為403:
import requestsr = requests.get("https://www.zhihu.com/explore") print(r.text)運行結果:
但如果加上 headers 并加上 User-Agent 信息,那就沒問題了:
import requestsheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' } r = requests.get("https://www.zhihu.com/explore", headers=headers) print(r.text)?運行結果:?
?此時可以看到加請求頭成功了。
為什么加請求頭??加上后可以模擬正常瀏覽器,防止被反扒。
3.5 知乎爬取+反扒技術
先獲取cookies:
import requests headers={'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11' } #請求頭 url='http://www.zhihu.com' r=requests.get(url=url,headers=headers) print(r.cookies)運行結果:
?或者登錄知乎,找到cookie:
?用這里的cookie來獲取網頁:
import requests headers={'Cookie':'_zap=05c6669b-d609-4b2d-836d-c4e713ed7831; d_c0="AFAfZacmRBOPTjQC-e4owqO1ysBeTeL3Vzw=|1623771050"; _xsrf=bqDX2DchG0ZA7EC9pkRRGEaVn3QkTrZi; captcha_session_v2="2|1:0|10:1636804292|18:captcha_session_v2|88:WjRRYXljbms2MmtweWJzMU9SQ1NrRlpPa2Q0ZytFWlJ0THpud2ZJQ1YxUktQbEg3a0EyTWNnYUprdUNhUW9qbQ==|0c9ffe3bd4b71219514487843501772ea80b4d14e4009a776f9a7529f4a56613"; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1636541465,1636541647,1636771333,1636804292; l_n_c=1; r_cap_id="YmNjZjMyOGVlZTM3NDRlNjlkYTkxZTY1Yjg1ODdhMjA=|1636804293|d3a977b05d2ed03f94aa4cc909fbb3232619c402"; cap_id="M2NkNWEzZDRkYmMwNDYwZThkMmRhNDU0M2QzZWU5ZGE=|1636804293|b9ec3e1451d5cd873d86525d785868acfa08c556"; l_cap_id="MjA5MGU4YjUyOGZhNGZlYWI3NzY0NGQ1ZWY5MjcyYmM=|1636804293|9ec9d7a50eb48b4e5450a2962e8090f86bf1281c"; n_c=1; SESSIONID=iachyVQaPqsWF2xcGJGC7c7RvcJvrlusR39loCQax90; __snaker__id=dYZWp8JZry4pPHne; JOID=VFsUAknVovxY469NX9IDpZ1o-iVLucGfM578Hj6B1o0PppkwPh8GcD7iqE9cjgkePw8VMqkDcY9vrgPNPl3u4uc=; osd=UV8UB0zQpvxd5qpJX9cGoJlo_yBOvcGaNpv4HjuE04kPo5w1Oh8DdTvmqEpZiw0eOgoQNqkGdIprrgbIO1nu5-I=; gdxidpyhxdE=7GzbIgu7wGey6y7Z4EeYzrtLlNOZOi08rMg9VqGGe%5Cs2tG9dg0lGBcPR%2BWxzp0u0eY3fRqE%5C1USNlC8qYP4lkOhjflbMytQvptR4ERWDs%5Ck5WyN40f%2FkwXx0cWg60pasJBZBPHI%2FGH66x5r3m2Ogsly%2BNpDDUt6T0qN%2F1vaur8USEdZT%3A1636805203141; _9755xjdesxxd_=32; z_c0=Mi4xdzNpOEV3QUFBQUFBVUI5bHB5WkVFeGNBQUFCaEFsVk56X1I4WWdBb2VFN0ZJUzQ3RVJDRGNVT2FmdDYxT0xXNXV3|1636804303|204653c41cd7c89747145d10e635c8403ba38549; tst=r; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1636804313; NOT_UNREGISTER_WAITING=1; KLBRSID=b5ffb4aa1a842930a6f64d0a8f93e9bf|1636804319|1636804289','User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11','host':'www.zhihu.com', } url='http://www.zhihu.com' r=requests.get(url=url,headers=headers) print(r.text)運行結果:
?返回結果有知乎里的相關內容,這樣就是成功登錄知乎了
再提一點session,它可以實現同一個站點進去不同頁面:
運行結果:
3.6 抓取二進制數據
如果想抓取圖片、音頻、視頻等文件,應該怎么辦呢?
圖片、音頻、視頻這些文件本質上都是由二進制碼組成的,由于有特定的保存格式和對應的解析方式,我們才可以看到這些形形色色的多媒體。所以,想要抓取它們,就要拿到它們的二進制碼。
3.6.1 示例一
下面以 GitHub 的站點圖標為例來看一下:
import requestsr = requests.get("https://github.com/favicon.ico") print(r.text) print(r.content)運行結果:
?可以注意到,前者出現了亂碼,后者結果前帶有一個 b,這代表是 bytes 類型的數據。由于圖片是二進制數據,所以前者在打印時轉化為 str 類型,也就是圖片直接轉化為字符串,這理所當然會出現亂碼。
接著,我們將剛才提取到的圖片保存下來:
運行后即可保存完成!!!可以自己設定保存位置哦!!
3.6.2 示例二
以爬取我自己的頭像為例子:
保存代碼如下,運行即可保存,位置資源!!!:?
import requests headers={'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', } url='https://profile.csdnimg.cn/2/B/0/1_qq_25990967.jpg' r = requests.get(url=url,headers=headers) with open('phpto.jpg', 'wb') as f:f.write(r.content)3.7 美女私房照爬取( 準備發車)
第一部分:定義要爬取的標簽和正在爬取的頁數
def UserUrl(theme,pagenum):url = "https://tuchong.com/rest/tags/%(theme)s/posts?page=%(pagenum)s&count=20&order=weekly" % {'theme': urllib.parse.quote(theme), 'pagenum': pagenum}#print(url)return url?第二部分:防止反扒
def GetHtmltext(url):head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"}try:r = requests.get(url, headers=head, timeout=30)r.raise_for_status() #如果返回的狀態碼不是200,就到except中return rexcept:pass第三部分:定義獲取一個pagenum頁面中的所有圖集的URL鏈接的函數
def PictureFatherUrl(user_url):try:raw_data = GetHtmltext(user_url)j_raw_data = json.loads(raw_data.text) #將獲取的網頁轉化為Python數據結構# print(j_raw_data)father_url = [] #將每個圖集的url定義為father_url的一個列表for i in j_raw_data['postList']: #解析出的j_raw_data是一個多重字典,在這里先將postList字典的內容取出來father_url.append(i['url']) #然后再取出鍵為“url”的值return father_urlexcept:return第四部分:定義獲取一個圖集中所有圖片的url鏈接
def PictureUrl(url):try:html = GetHtmltext(url)#利用正則表達式來匹配url_list = list(re.findall('<img id="image\d+" class="multi-photo-image" src="([a-zA-z]+://[^\s]*)" alt="">', html.text))return url_listexcept:pass第五部分:
#定義一個圖集中所有圖片的下載 def Download(url):url_list = PictureUrl(url)for i in url_list:r = GetHtmltext(i)file_name = os.path.join(save_path, i.split('/')[-1])with open(file_name, 'wb') as f:f.write(r.content)f.close()time.sleep(random.uniform(0.3, 0.5)) #為防止被反爬,在這里random了0.3-0.5的數,然后在下載一張圖片后,sleep一下print('下載成功保存至 %s' % file_name)主函數部分:
if __name__ == '__main__':theme = input("你選擇的標簽(如果你不知道有什么標簽,去https://tuchong.com/explore/去看看有什么標簽吧,輸入不存在的標簽無法下載哦):")pagenum_all = int(input("你要爬取的頁數(不要太貪心哦,數字太大會被封IP的):"))save_path = os.path.join(theme)m = 0if not os.path.exists(save_path):os.makedirs(save_path)print("我知道你沒有創建保存路徑,我把文件存在和此腳本同樣的路徑下的叫做“ %s ”的文件夾下面了" % theme)for i in range(1, pagenum_all+1):n = 0m += 1print("正在下載第%d頁,一共%d頁" % (m, pagenum_all))user_url = UserUrl(theme, i)father_url = PictureFatherUrl(user_url)for j in father_url:n += 1print("正在下載第%d套圖,一共%d套圖" % (n, len(father_url)))Download(j)time.sleep(random.randint(6, 10)) #同樣為了反爬,也random了6-10之間的數,更真實的模擬人的操作完整源代碼如下:
#coding=gbkimport os import re import json import requests import time import urllib.parse import random#定義要爬取的標簽和正在爬取的頁數 def UserUrl(theme,pagenum):url = "https://tuchong.com/rest/tags/%(theme)s/posts?page=%(pagenum)s&count=20&order=weekly" % {'theme': urllib.parse.quote(theme), 'pagenum': pagenum}#print(url)return url#利用requests使用get方法請求url,使用User-Agent是為了防止被反爬,這樣使得我們的爬取行為更像人的行為 def GetHtmltext(url):head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"}try:r = requests.get(url, headers=head, timeout=30)r.raise_for_status() #如果返回的狀態碼不是200,就到except中return rexcept:pass#定義獲取一個pagenum頁面中的所有圖集的URL鏈接的函數 def PictureFatherUrl(user_url):try:raw_data = GetHtmltext(user_url)j_raw_data = json.loads(raw_data.text) #將獲取的網頁轉化為Python數據結構# print(j_raw_data)father_url = [] #將每個圖集的url定義為father_url的一個列表for i in j_raw_data['postList']: #解析出的j_raw_data是一個多重字典,在這里先將postList字典的內容取出來father_url.append(i['url']) #然后再取出鍵為“url”的值return father_urlexcept:return#定義獲取一個圖集中所有圖片的url鏈接 def PictureUrl(url):try:html = GetHtmltext(url)#利用正則表達式來匹配url_list = list(re.findall('<img id="image\d+" class="multi-photo-image" src="([a-zA-z]+://[^\s]*)" alt="">', html.text))return url_listexcept:pass#定義一個圖集中所有圖片的下載 def Download(url):url_list = PictureUrl(url)for i in url_list:r = GetHtmltext(i)file_name = os.path.join(save_path, i.split('/')[-1])with open(file_name, 'wb') as f:f.write(r.content)f.close()time.sleep(random.uniform(0.3, 0.5)) #為防止被反爬,在這里random了0.3-0.5的數,然后在下載一張圖片后,sleep一下print('下載成功保存至 %s' % file_name)#定義主函數 if __name__ == '__main__':theme = input("你選擇的標簽(如果你不知道有什么標簽,去https://tuchong.com/explore/去看看有什么標簽吧,輸入不存在的標簽無法下載哦):")pagenum_all = int(input("你要爬取的頁數(不要太貪心哦,數字太大會被封IP的):"))save_path = os.path.join(theme)m = 0if not os.path.exists(save_path):os.makedirs(save_path)print("我知道你沒有創建保存路徑,我把文件存在和此腳本同樣的路徑下的叫做“ %s ”的文件夾下面了" % theme)for i in range(1, pagenum_all+1):n = 0m += 1print("正在下載第%d頁,一共%d頁" % (m, pagenum_all))user_url = UserUrl(theme, i)father_url = PictureFatherUrl(user_url)for j in father_url:n += 1print("正在下載第%d套圖,一共%d套圖" % (n, len(father_url)))Download(j)time.sleep(random.randint(6, 10)) #同樣為了反爬,也random了6-10之間的數,更真實的模擬人的操作運行:按照提示輸入后回車
?后得到:
?當然,難道我的心只有美女小姐姐?NONONO!你只要輸入該網任意一個標簽的都可給下載下來,比如帥哥?你可以測試一下!!!
四、 POST 請求
前面我們了解了最基本的 GET 請求,另外一種比較常見的請求方式是 POST。
4.1 數據表單提交
使用 requests 實現 POST 請求同樣非常簡單,示例如下:
import requestsdata = {'name': 'germey', 'age': '22'} r = requests.post("http://httpbin.org/post", data=data) print(r.text)這里還是請求 http://httpbin.org/post,該網站可以判斷如果請求是 POST 方式,就把相關請求信息返回。
運行結果如下:
可以發現,我們成功獲得了返回結果,其中 form 部分就是提交的數據,這就證明 POST 請求成功發送了。
4.2 添加請求頭
代碼如下:
import requests import jsonhost = "http://httpbin.org/" endpoint = "post"url = ''.join([host,endpoint]) headers = {"User-Agent":"test request headers"}r = requests.post(url,headers=headers) print(r.text)運行結果:
可以看到User-Agent部分為我們添加的自定義請求頭。
4.3 提交json
假設我想提交json格式的內容:
# -*- coding:utf-8 -*- import requests import jsonhost = "http://httpbin.org/" endpoint = "post"url = ''.join([host,endpoint]) data = {"sites": [{ "name":"test" , "url":"https://blog.csdn.net/weixin_46211269?spm=1000.2115.3001.5343" },{ "name":"google" , "url":"https://blog.csdn.net/weixin_46211269/article/details/120703631?spm=1001.2014.3001.5501" },{ "name":"weibo" , "url":"https://blog.csdn.net/weixin_46211269/article/details/120659923?spm=1001.2014.3001.5501" }] }r = requests.post(url,json=data) # r = requests.post(url,data=json.dumps(data)) response = r.json() print(response)運行結果:
4.4 普通文件上傳
代碼:
# -*- coding:utf-8 -*- import requests import jsonhost = "http://httpbin.org/" endpoint = "post"url = ''.join([host,endpoint]) #普通上傳 files = {'file':open(r'D:\桌面\a.txt','rb') #打開文件路徑}r = requests.post(url,files=files) print (r.text)運行結果:
總結
以上是生活随笔為你收集整理的零基础爬虫requests初阶教程,手把手教你爬数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 宽字符串,C语言中的多字节字
- 下一篇: php文件夹重命名,PHP重命名和移动目