Python基础学习--基于尚硅谷python教学视频
Python學習
1.pycharm一些常用設置
設置通用代碼模板
2.注釋
單行注釋:#
多行注釋: ‘’’ ‘’‘’
3.變量類型
Number(數字) : int(有符號整形)、long(長整型,也可以代表八進制和十六進制)、float(浮點型)、complex(復數) 布爾類型:True、Flase String(字符串) List(列表) Tuple(元祖) Dictionary(字典)使用
# 變量類型的基本使用 # int money = 5000 # float money2 = 1.2# boolean 布爾 sex = True gender = False# String 字符串 使用的單引號或者雙引號 s = "111"# 單引號和雙引號的嵌套 s4 = '"嵌套"' print(s4) s5 = "'嘿嘿嘿'" print(s5)# list 列表name_list = ['周杰倫','復活科比'] print(name_list)# tuple 元組 age_tuple =(18,19,20) print(age_tuple)# dict 字典 # 應用場景 :scrapy框架使用 person = {"key":"value","age":18} print(person["key"])4.查看變量數據類型
使用type方法判斷變量的數據類型
a = 1 print(a) print(type(a))# float b = 2.5 print(b) print(type(b))# boolean c = True print(c) print(type(c))# String d = "中國" print(d) print(type(d))# List e = ["str",111] print(e) print(type(e))# Dist f = {"a":"aaa","b":222} print(f) print(type(f))# Tuple g = (1,2,3,4,5) print(g) print(type(g))5.類型轉換
# 字符串中特殊字符類型不能被轉換 # 轉換成整形 # str ---> int str = '123' print(type(str)) num = int(str) print(type(num))# float --> int a = 1.23 print(type(int(a)))# boolean --> int False = 0 True = 1 b = True print(type(int(b)))6.賦值運算符
d,e,f = 1,2,3 print(d)7.邏輯運算符
# 邏輯運算符 and:與 or:或 not:非 # and:都成立為True # or:一個成立為True,兩個都不成立為False # not:邏輯非,成立的為False,不成立的True8.輸入輸出
輸出
# 普通輸出 print("1111")# 格式化輸出 # scrapy框架的時候 excel文件 mysql redis age = 22 name = '張三' print("我的年齡是:"+str(age)) # %s 代表著字符串 %d 代表著數值 print("我的名字是:%s,我的年齡是:%d" % (name,age))輸入
# 輸入 code = input('請輸入驗證碼:') print("我的驗證碼是:%s" %code)9.if語句
age = 22 if age>18:print("你成年啦!")score = int(input('請輸入成績:')) if score>=90:print("優秀") elif score>=80:print("良好") elif score>=70:print("及格") else:print("不及格")10.for循環語句
# 循環字符串 # range(5) # range(1,6) # range(1,10,3) # 循環一個列表s = 'china' # i是字符串中的字符變量(c、h、i、n、a) # s是代表的是要遍歷的數據 # range(5) 0~4 左閉右開區間(0,5) # for i in range(5): # print(i)# range(1,6) # for i in range(1,6): # print(i)# range(1,10,3) # i=i+3 只要小于<10 步長 # for i in range(2,10,3): # print(i)# 循環一個列表 a_list = ['zs','ls','ww'] for i in range(0,len(a_list)):print(i)# len() 判斷列表中元素的個數 print(len(a_list))11.字符串高級
| 查找內容:find | 查找指定內容在字符串中是否存在,如果存在就返回該內容在字符串中第一次出現的開始位置索引值,如果不存在,則返回-1. |
| 判斷:startswith,endswith | 判斷字符串是不是以誰誰誰開頭/結尾計算 |
| 出現次數:count | 返回 str在start和end之間 在 mystr里面出現的次數 |
| 替換內容:replace | 替換字符串中指定的內容,如果指定次數count,則替換不會超過count次。 |
| 切割字符串:split | 通過參數的內容切割字符串 |
| 修改大小寫:upper,lower | 將字符串中的大小寫互換 |
| 空格處理:strip | 去空格 |
| 字符串拼接:join | 字符串拼接 |
12.列表高級
1.添加
# append 默認在列表的最后添加數據 food_list = ['老八秘制小漢堡','小雞燉蘑菇'] print(food_list) food_list.append('五花肉') print(food_list)# insert index的值就是你想插入數據的那個下標 char_list = ['a','c','d'] print(char_list) char_list.insert(1,'b') print(char_list)# extend 可以迭代數據 num_list = [1,2,3] num1_list = [4,5,6] num_list.extend(num1_list) print(num_list)2.修改
# 修改 city_list = ['北京','武漢','重慶'] print(city_list) # 將列表中的元素的值修改 city_list[2] = '大連' print(city_list)3.查找
# 查找 in判斷某一個元素是否在某一個列表中 food2_list = ['老八秘制小漢堡','小雞燉蘑菇','東北亂燉'] # 判斷一下在控制臺輸入的數據是否在列表中 fond = input('請輸入您想吃的食物') if fond in food2_list:print("在") else:print("不在")# not in 判斷某一個元素不在某一個列表中 ball_list = ['籃球','臺球'] ball = input("請輸入您喜歡的球類:") if ball not in ball_list:print("不在") else:print('在')4.刪除
- del:根據下標進行刪除
- pop:刪除最后一個元素
- remove:根據元素的值進行刪除
13.元組高級
a_tuple = (1,2,3,4) print(a_tuple[0])# 元祖是不可以修改里面的內容 # a_tuple[0] = 2 是錯誤的# 1.元組和列表的區別是列表可以修改,元組不能修改 a_list = [1,2,3,4] print(a_list[0]) a_list[0] = 5 print(a_list[0])# 2.當元組中只有一個元素的時候,那么他是整型數據 b_tuple = (5) print(type(b_tuple)) # 定義只有一個元素的元組,需要在唯一元素后面寫一個逗號 c_tuple = (5,) print(type(c_tuple))14.切片
切片是指對操作的對象截取其中一部分的操作。字符串、列表、元組都支持切片操作
切片的語法:[起始:結束:步長],也可以簡化使用[起始:結束]
s = 'hello world' # 在切片中直接寫一個下標 print(s[0]) #h# 起始:結束,不包含結束,左閉右開 print(s[0:4]) #hell# 起始:,代表起始開始到末尾 print(s[1:]) #ello world# :結尾,從頭到結尾 print(s[:4]) #hell# 起始:結束:步長 到下標為6的位置結束,每次增長2個 print(s[0:6:2]) # hlo15.字典高級
查詢
# 定義一個字典 person = {'name':'張三','age':'22'}# 訪問person的name print(person['name'])# 獲取一個不存在的key # print(person['sex']) # errorKey# 第二種獲取方法 person.get('name') print(person.get('name')) # 使用.get獲取一個不存在的key不會報錯會給一個None print(person.get('key')) # None修改
person2 = {'name':'李四','age':'23'}# 修改之前的字典 print(person2.get('name'))# 修改name的值為法外狂徒 person['name'] = '法外狂徒' print(person['name'])添加
person3 = {"name":'老大'} # 如果使用變量名字['鍵'] = 數據時,這個鍵如果在字典中不存在 那么就會變成新增元素 person3['age'] = '18' print(person3['age'])刪除
# 刪除 # del # (1)刪除字典中指定的某一個元素 person4 = {'name':"老馬",'age':18} # 刪除前 print(person4) del person4['age'] # 刪除后 print(person4) # (2)刪除整個字典 # del person4 # print(person4) # clear # (3) 清空字典 但是保留字典對象 person4.clear() print(person4) # {} 刪除整個字典但是不刪除結構遍歷
# 遍歷 person5 = {"name":"楊松","age":23,"sex":"男"}# (1) 遍歷字典的key # 字典.keys() for key in person5.keys():print(key)# (2) 遍歷字典的value for val in person5.values():print(val) # (3) 遍歷字典的key和value for key,val in person5.items():print(key,val)for key in person5.items():print(key)# (4) 遍歷字典的項/元素 for item in person5.items():print(item)16.函數
函數的定義與調用
# 定義函數 def f():print("歡迎")# 調用函數 f()函數參數的使用
# 使用函數計算1和2的和 def add(a,b):print(a+b)# 位置參數 add(3,4) # 關鍵字傳參 add(b = 100,a = 200)函數返回值
def add(a,b):return a+bc = add(3,4) print(c)17.文件
文件的打開與關閉
# 文件的打開與關閉 # open(文件路徑,訪問模式) # 模式:w 可寫 # r 可讀 f = open('test.txt','w')f.write("hello world")# 文件夾是不可以創建的,需要手動創建 f = open("demo/text.txt","w") f.write("hello python")# 文件的關閉 fp = open("demo/a.txt",'w') fp.write("hello") fp.close()文件路徑
絕對路徑:絕對位置,完整地描述了目標的所在地,所有目錄層級關系是一目了然的。
- 例如:E:\python,從電腦的盤符開始,表示的就是一個絕對路徑。
相對路徑:是從當前文件所在的文件夾開始的路徑。
- test.txt,是在當前文件查找 test.txt文件
- ./test.txt,也是當前文件夾中查找 test.txt文件,./表示的是當前文件夾
- ../test.txt,從當前文件夾的上一級文件夾里查找 test.txt文件。../表示的是上一級文件夾
- demo/test.txt,在當前文件夾里查找 demo這個文件夾,并在這個文件夾里查找 test.txt文件
文件的讀寫
# 寫數據 # write方法 fp = open("demo/test.txt","a") fp.write("hello world,I am here\n"*5) fp.close()# 如果再運行這段代碼,可以覆蓋代碼 # 想在執行之后追加數據,更改模式 a # 如果模式變為了a 那么就會執行追加的操作# 讀數據 fp = open("demo/test.txt", "r") # 默認情況下,read是一字節一字節的讀,效率比較低 content = fp.read() print(content)# readline讀取一行數據 content = fp.readline() print(content)# readlines可以按照行來讀取 但是會將所有的數據都讀取到,并且以一個列表的形式返回 # 而列表的元素是一行一行的數據 content = fp.readlines() print(content)18.文件的序列化和反序列化
通過文件操作,我們可以將字符串寫入到一個本地文件。但是,如果是一個對象(例如列表、字典、元組等),就無法直接寫入到一個文件里,需要對這個對象進行序列化,然后才能寫入到文件里。
設計一套協議,按照某種規則,把內存中的數據轉換為字節序列,保存到文件,這就是序列化,反之,從文件的字節序列恢復到內存中,就是反序列化。
Python中提供Json這個模塊用來實現數據的序列化和反序列化。
- 對象----->字節序列 === 序列化
- 字節序列----->對象 ===反序列化
JSON模塊
JSON是一種輕量級的數據交換標準。JSON的本質是字符串。
使用JSON實現序列化
JSON提供了dump和dumps方法,將一個對象進行序列化。
dumps方法的作用是把對象轉換成字符串,它本身不具備將數據寫入到文件的功能。
# fp = open("demo/test.txt",'w') # # 默認情況我們只能將字符串寫入文件中 # fp.write("hello world") # fp.close()# fp = open('test.txt','w') # name_list = ['zhangsan','lisi'] # # 列表不能寫入文件中 如果想寫入到文件,那么必須使用序列化操作 # fp.write(name_list)# 序列化的2種方式 # dumps() # (1) 創建一個文件 fp = open('demo/test.txt','w') # (2) 定義一個列表 name_list = ['zhangsan','lisi'] # (3) 導入json模塊到該文件 import json# 序列化 # 將python對象變成json字符串 # 我們在使用scrapy框架的時候,該框架會返回一個對象 我們要將對象寫入到文件中,就要使用json.dumps names = json.dumps(name_list)# 將names寫入到文件中 fp.write(names)fp.close()# dump # 在將對象轉換為字符串的同時,指定一個文件的對象,然后把轉換后的字符串寫入到這個文件里 import jsonfp = open("demo/test.txt", 'w') name_list = ['zss', 'ls'] import json json.dump(name_list,fp) fp.close()# 反序列化 # 將json字符串變成一個python對象 fp = open("demo/test.txt",'r') content = fp.read() print(content) # <class 'str'> print(type(content)) # loads 加載字符串 # 反序列化json對象為python對象 result = json.loads(content) # 轉換之后 print(result) # <class 'list'> print(type(result)) fp.close()# load 加載文件 fp = open("demo/test.txt",'r') content = json.load(fp) print(content) print(type(content))19.異常
try:
可能出現異常的代碼
except 異常的類型
友好的提示
20.Urllib
一、反爬手段 User‐Agent: User Agent中文名為用戶代理,簡稱 UA,它是一個特殊字符串頭,使得服務器能夠識別客戶使用的操作系統及版本、CPU 類型、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語言、瀏覽器插件等。 代理IP 西次代理 快代理 什么是高匿名、匿名和透明代理?它們有什么區別? 1.使用透明代理,對方服務器可以知道你使用了代理,并且也知道你的真實IP。 2.使用匿名代理,對方服務器可以知道你使用了代理,但不知道你的真實IP。 3.使用高匿名代理,對方服務器不知道你使用了代理,更不知道你的真實IP。 驗證碼訪問- 打碼平臺 - 云打碼平臺 - 超級🦅動態加載網頁 網站返回的是js數據 并不是網頁的真實數據selenium驅動真實的瀏覽器發送請求數據加密分析js代碼1.Urllib庫的使用
基本使用
# 使用urllib來獲取百度首頁的源碼# (1) 定義一個url 就是你要訪問的地址 import urllib.requesturl = "http://www.baidu.com" # (2) 模擬瀏覽器向服務器發送請求 response = urllib.request.urlopen(url)# (3) 獲取響應中的頁面的源碼 # read方法 返回的是字節形式的二進制數據 # 我們要將二進制的數據轉換為字符串 # 二進制===>字符串 === 解碼 decode('編碼格式') content = response.read().decode("utf-8")# (4) 打印數據 print(content)2.一個類型和六個方法
# 一個類型 HTTPResponse # 六個方法 read()、readline()、readlines()、getcode()、geturl()、getheaders()import urllib.requesturl = "http://www.baidu.com"# 模擬瀏覽器向服務器發送請求 resp = urllib.request.urlopen(url)# 一個類型和六個方法 <class 'http.client.HTTPResponse'> # print(type(resp))# 按照一個字節一個字節讀取 # content = resp.read() # print(content) # resp.read(數字) 代表返回多少個字節 b'<!DOC' # content = resp.read(5) # print(content)# readline() :讀取一行 # content = resp.readline() # print(content)# readlines() :讀取多行 # content = resp.readlines() # print(content)# 返回狀態碼 如果是200 那么證明我們的邏輯沒有錯 # print(resp.getcode())# 返回的是url地址 # print(resp.geturl())# 獲取是一個狀態信息 print(resp.getheaders())3.下載
# 下載網頁 import urllib.requesturl_page = 'http://www.baidu.com' # url代表的是下載的路徑,filename文件的名字 urllib.request.urlretrieve(url_page,"baidu.html")# 下載圖片 url_img = 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF' urllib.request.urlretrieve(url_img,'bg.jpg')# 下載視頻 video_url = 'http://pgcvideo-cdn.xiaodutv.com/2882354867_1584684956_2018031615444820180316174016.mp4?authorization=bce-auth-v1%2Fc308a72e7b874edd9115e4614e1d62f6%2F2018-03-16T09%3A41%3A04Z%2F-1%2F%2Fe45da341e8dc544862d72871e3b949a9d3d36e3d651e4925e5778d961e3f6db1&responseCacheControl=max-age%3D8640000&responseExpires=Sun%2C+24+Jun+2018+17%3A41%3A04+GMTmp4&time=1657632635&xcode=829989cc93c9530b4ac98bacb4c3d44877e7bc56c0ecf6ed&_=1657548647900' urllib.request.urlretrieve(video_url,'yyds.mp4')4.請求對象的定制
UA介紹:User Agent中文名為用戶代理,簡稱 UA,它是一個特殊字符串頭,使得服務器能夠識別客戶使用的操作系統及版本、CPU 類型、瀏覽器及版本。瀏覽器內核、瀏覽器渲染引擎、瀏覽器語言、瀏覽器插件等
# url的組成 # http/https(更加安全) # 協議 主機 端口號 路徑 參數 錨點 # http 80 # https 443 # mysql 3306headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" } # 因為urlopen方法中不能存儲字典 所以headers不能傳遞進去 # 請求對象的定制 # 注意 因為參數的順序問題,不能直接寫url和headers,中間還有data,所以我們需要關鍵字傳參 request = urllib.request.Request(url=url,headers=headers) resp = urllib.request.urlopen(request) content = resp.read().decode("utf-8") print(content)5.編解碼
1、get請求方式:urllib.parse.quote()
# 需求: 獲取https://www.baidu.com/s?wd=周杰倫 的網頁源碼 import urllib.requesturl = "https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6"# 請求對象的定制為了解決反爬的第一種手段 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" } # 將周杰倫三個字變成unicode編碼的格式 # 我們需要依賴于urllib.parse name = urllib.parse.quote("周杰倫")print(name)request = urllib.request.Request(url=url,headers=headers) # 模擬瀏覽器向服務器發送請求resp = urllib.request.urlopen(request) # 獲取響應的內容 content = resp.read().decode("utf-8") # 報錯 :'ascii' codec can't encode characters in position 10-12: ordinal not in range(128) ASCII碼不能解碼中文 # print(content)2、get請求方式:urllib.parse.urlencode()
主要解決多個中文參數時候
# urlencode應用場景:多個參數的時候# https://www.baidu.com/s?wd=周杰倫&sex=男 import urllib.parse import urllib.request # data = { # 'wd':'周杰倫', # 'sex':'男', # 'locatin':'中國臺灣省' # } # content = urllib.parse.urlencode(data) # print(content)# 獲取https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7base_url = "https://www.baidu.com/s?" data = {'wd': '周杰倫','sex': '男','locatin': '中國臺灣省' } new_data = urllib.parse.urlencode(data) base_url += new_data print(base_url) headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" } # 請求對象的定制 request = urllib.request.Request(url=base_url, headers=headers) # 模擬瀏覽器向服務器發送請求 resp = urllib.request.urlopen(request)content = resp.read().decode("utf-8") print(content)6.Post請求方式
post請求的參數,必須要進行編碼 編碼之后必須調用encode方法 data = urllib.parse.urlencode(data).encode("utf-8") 參數是放在請求對象定制的方法中 request = urllib.request.Request(url=url,data=data,headers=headers) import urllib.request import urllib.parse# (1) post請求 url = "https://fanyi.baidu.com/sug" headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ""Safari/537.36 " }data = {'kw': 'spider' }# (2) post請求的參數,必須進行編碼 data = urllib.parse.urlencode(data).encode("utf-8")# (3) post的請求參數是不會拼接在url的后面,而是需要放在請求定制對象的參數中 request = urllib.request.Request(url=url,data=data,headers=headers)# (4) 模擬瀏覽器向服務器發送請求 resp = urllib.request.urlopen(request) # (5) 最后查詢內容時解碼 content = resp.read().decode("utf-8") print(content)百度詳細翻譯
import urllib.request import urllib.parseurl = "https://fanyi.baidu.com/v2transapi?from=en&to=zh" # 在network中的v2transapi?from=en&to=zh中headers = {'Accept': '*/*',# 'Accept-Encoding': 'gzip, deflate, br', 這句話需要注釋,接收的格式不是utf-8'Accept-Language': 'zh-CN,zh;q=0.9','Acs-Token': '1657609209232_1657634073392_QzvIJLYMoJlfU9K6oVDIEFqoL28DWbm988ZKnjR3xk8/Sa3rfbEgNkdwkbNM+hDMZzMdrF6a5Vwq6oR8XYtzy0d5DASp2ylIydmE62BTPpaZI/R15QT4dmatC0qtrzBFaBMCPzNtKYJxKugFW+JQzSu1gJkM3jvFBfQasudzEqAta6zzAZjptPRIg1leKg/oWvn5soJ4Marpa4nkA7jdSCs9Z0CoUuMGKxxxX46k7oLg+2WKmaolL8kMNDrBnwuo32t3c8UVkzqV9WRoVwe8jYSmCt1ghiaDRUhmxrdyutg=','Connection': 'keep-alive','Content-Length': '136','Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8','Cookie': 'BIDUPSID=D51BF5882EE7B65BD4075DB6F624444E; PSTM=1649342254; BAIDUID=D51BF5882EE7B65B161C80EE82019036:FG=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; REALTIME_TRANS_SWITCH=1; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; H_WISE_SIDS=110085_127969_131862_176399_179349_180636_185636_189755_191527_194085_196426_196527_197096_197471_197711_199568_204919_207234_207540_208721_209568_210302_210321_210643_211312_211557_211732_211953_212296_212726_212739_212798_212870_212912_213039_213059_213094_213278_213359_213485_213508_214093_214655_214789_215070_215120_215126_215731_215833_215856_215957_216044_216252_216295_216353_216416_216449_216569_216595_216635_216646_216656_216840_216913_216927_216937_216942_217088_217320_217452_217516_217584; BDUSS=lBHbDZNNVpieGxifjhwemJzMGljVzcxVHV-aTZEcjJ-YXBiZ2F0SjNVak9nLTlpRVFBQUFBJCQAAAAAAAAAAAEAAABWgsFN0MSwtsrvueJpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM72x2LO9sdib; BDUSS_BFESS=lBHbDZNNVpieGxifjhwemJzMGljVzcxVHV-aTZEcjJ-YXBiZ2F0SjNVak9nLTlpRVFBQUFBJCQAAAAAAAAAAAEAAABWgsFN0MSwtsrvueJpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM72x2LO9sdib; BDRCVFR[brmhvwvKpQR]=mk3SLVN4HKm; delPer=0; PSINO=2; ZFY=ak38XErjDSK5YKTfi2mIe1QGJTriLqXfChfud3qtFDM:C; H_WISE_SIDS_BFESS=110085_127969_131862_176399_179349_180636_185636_189755_191527_194085_196426_196527_197096_197471_197711_199568_204919_207234_207540_208721_209568_210302_210321_210643_211312_211557_211732_211953_212296_212726_212739_212798_212870_212912_213039_213059_213094_213278_213359_213485_213508_214093_214655_214789_215070_215120_215126_215731_215833_215856_215957_216044_216252_216295_216353_216416_216449_216569_216595_216635_216646_216656_216840_216913_216927_216937_216942_217088_217320_217452_217516_217584; RT="z=1&dm=baidu.com&si=dh45lyulsgc&ss=l5gs5ber&sl=1&tt=nz&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=1g2&ul=b8n&hd=b8s"; BAIDUID_BFESS=7E6E2DBCD1049094EF0AAC7C26407A69:FG=1; BDRCVFR[S4-dAuiWMmn]=FZ_Jfs2436CUAqWmykCULPYrWm1n1fz; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[X_XKQks0S63]=mk3SLVN4HKm; BDRCVFR[Q5XHKaSBNfR]=mk3SLVN4HKm; BDRCVFR[tox4WRQ4-Km]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; BA_HECTOR=002k848l0h21a10h0hag1caq1hcqpqm17; H_PS_PSSID=26350; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; APPGUIDE_10_0_2=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1657633745; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1657634066; ab_sr=1.0.1_NWFlMWJhMzUzZjNjODgxZTZjZTUwOWYwNjNlNjE1MmRiZTg1MTcxNzNlYzMwZGJiYzNkZGFkMGI4MDY2NDNhMjNkYzY5NjVlYTI0N2ViNmVhMGYyZWMyOGY0ZjMyOGE2ZGMzZGE5MjE4OTMxYTFiZDczMTA2ZjFlNTdkZWRhMDVkNDcxMDM0YzVmZTlhNGIwYTY2ZjE3ZmUwOTQ3MGM3YTc3YTc5YzcxMjY4ODc4YzJhYzVhNGVmM2Y0MGQ1MWE5','Host': 'fanyi.baidu.com','Origin': 'https://fanyi.baidu.com','Referer': 'https://fanyi.baidu.com/','sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'same-origin','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36','X-Requested-With': 'XMLHttpRequest', }data = {"from": "en","to": "zh","query": "spider","transtype": "realtime","simple_means_flag": "3","sign": "63766.268839","token": "c343c5a7b4fb792c974092c83cecf80f","domain": "common" } # post請求的參數必須編碼,還必須調用encode方法 data = urllib.parse.urlencode(data).encode("utf-8")# 請求對象的定制 request = urllib.request.Request(url=url,data=data,headers=headers)# 模擬瀏覽器向服務器發送請求 resp = urllib.request.urlopen(request)content = resp.read().decode('utf-8') # {"errno":997,"errmsg":"\u672a\u77e5\u9519\u8bef","query":"spider","from":"en","to":"zh","error":997} print(content)import json obj = json.loads(content) # {'errno': 997, 'errmsg': '未知錯誤', 'query': 'spider', 'from': 'en', 'to': 'zh', 'error': 997} print(obj)7.Ajax的get請求
get請求豆瓣的第一頁內容
# get請求 # 獲取豆瓣電影第一頁的數據,并且保存起來 import urllib.request import urllib.parseurl = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100:90&action=&start=0&limit=20"headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" } # (1)請求對象的定制 request = urllib.request.Request(url=url, headers=headers) # (2)獲取響應數據 resp = urllib.request.urlopen(request) content = resp.read().decode("utf-8") print(content) # (3)數據下載到本地 # open方法默認情況下使用的gbk的編碼,如果我們要想保存漢字,那么需要在open方法中指定編碼格式為utf-8 fp = open("demo/douban.json","w",encoding='utf-8') fp.write(content) fp.close()-
get請求豆瓣電影前十頁
# limit代表一頁20條 # https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=0&limit=20# https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=20&limit=20# https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=40&limit=20# page 1 2 3 4 # start 0 20 40 60# start = (page-1)*20# 下載豆瓣電影前十頁的數據# (1) 請求對象的定制 # (2) 獲取響應數據 # (3) 下載數據import urllib.parse import urllib.request# 獲取request def create_request(page):base_url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&"data = {"start": (page - 1) * 20,"limit": 20}headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"}data = urllib.parse.urlencode(data)new_url = base_url + datarequest = urllib.request.Request(url=new_url, headers=headers)return request# 獲取內容 def get_content(request):resp = urllib.request.urlopen(request)content = resp.read().decode("utf-8")return content# 下載數據 def download_data(content,page):fp = open("demo/douban_"+str(page)+'.json', "w",encoding='utf-8')fp.write(content)fp.close()# 程序的入口 if __name__ == '__main__':start_page = int(input("請輸入起始的頁碼:"))end_page = int(input("請輸入結束的頁碼:"))for page in range(start_page, end_page + 1):# 每一頁都有自己請求對象的定制request = create_request(page)# 獲取響應數據content = get_content(request)# 下載download_data(content,page)
8.Ajax的post請求
-
post請求肯德基溫州門店信息
# 請求地址 第一頁 # http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword # post請求 # cname: # pid: # keyword: 太原 # pageIndex: 1 # pageSize: 10# 第二頁 # http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword # post請求 # cname: # pid: # keyword: 太原 # pageIndex: 2 # pageSize: 10import urllib.request import urllib.parse# 獲取request def create_request(page):base_url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword"headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/103.0.0.0 Safari/537.36 "}# 獲取data數據data = {"cname":"","pid":"","keyword": "太原","pageIndex": page,"pageSize": 10}# post請求參數,必須編碼data = urllib.parse.urlencode(data).encode("utf-8")# post的請求參數是不會拼接到url后面,需要放在請求定制對象的參數中request = urllib.request.Request(url=base_url,data=data,headers=headers)return requestdef create_content(request):# 模擬瀏覽器向服務器發送請求resp = urllib.request.urlopen(request)content = resp.read().decode("utf-8")return contentdef download_data(content, page):fp = open("demo/kfc/kfc_"+str(page)+".json","w",encoding="utf-8")fp.write(content)fp.close()if __name__ == '__main__':start_page = int(input("請輸入起始頁碼:"))end_page = int(input("請輸入結束頁碼:"))for page in range(start_page,end_page+1):# 每一頁都有請求對象的定制request = create_request(page)# 獲取每頁的內容content = create_content(request)# 封裝數據到文件中download_data(content, page)
9.URLError\HTTPError
import urllib.request import urllib.error # 正確的url : "https://blog.csdn.net/sulixu/article/details/119818949" url = "https://blog.csdn.net/sulixu/article/details/119818949" # urllib.error.HTTPError: HTTP Error 404: Not Found headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ""Safari/537.36 " }try:# 請求對象的定制request = urllib.request.Request(url=url, headers=headers)# 模擬瀏覽器向服務器發送請求resp = urllib.request.urlopen(request)# 獲取頁面內容content = resp.read().decode("utf-8")print(content) except urllib.error.HTTPError:print("系統正在升級.....")10.微博的cookie登錄
適用的場景:數據采集的時候,需要繞過登錄,然后進入到某個頁面
cookie是headers中的關鍵信息,如果有登錄之后的cookie,那么我們可以攜帶著cookie進入到任何頁面
# 適用的場景:數據采集的時候,需要繞過登錄,然后進入到某個頁面 # 個人信息頁面是utf-8 但還是報錯了編碼錯誤,因為并沒有進入到個人信息頁面,而是跳轉到了登錄頁面import urllib.requesturl = "https://weibo.cn/5873215474/profile"headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ""Safari/537.36 ","cookie": "_T_WM=8976340b3c92efa3a03b7fb4682e53d4; ""SCF=AkwF768NP5yG7U7IM_1mAFgkAANBFgxO8xLzIe8aDTyPsRX0h0nT1lXgYkJh7-VsFN4BnJCBHNWpmoTL54XJ0gQ.; ""SUB=_2A25Py-vdDeRhGeNG7FET8SvIzDiIHXVtN_WVrDV6PUJbktAKLXmikW1NSwrsX3IMnAf8hBG_QjQwt96xry03Xpu3; ""SUBP""=0033WrSXqPxfM725Ws9jqgMF55529P9D9W592gFJm2N2necZ9sUyMAdh5NHD95Qf1hM0eo2fShMXWs4DqcjSxP9LMJUjdNUNUNUNTBtt; SSOLoginState=1657772941 " }# 請求對象的定制 request = urllib.request.Request(url=url,headers=headers) # 模擬瀏覽器向服務器發送請求 resp = urllib.request.urlopen(request) # 獲取內容 content = resp.read().decode("UTF-8") print(content)# 將數據保存在本地 with open("demo/weibo.html",'w',encoding='UTF-8') as fp:fp.write(content)11.Handler處理器
# 需求 使用handler來訪問百度 獲取網頁源碼 import urllib.requesturl = "http://www.baidu.com"headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ''Safari/537.36', }request = urllib.request.Request(url=url, headers=headers)# handler build_opener open# (1) 獲取handler對象 handler = urllib.request.HTTPHandler()# (2) 獲取opener對象 opener = urllib.request.build_opener(handler)# (3) 調用open方法 response = opener.open(request)content = response.read().decode("utf-8")print(content) import urllib.requesturl = "https://www.baidu.com/s?wd=ip"headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ''Safari/537.36', }# 請求對象的定制 request = urllib.request.Request(url=url,headers=headers)# 模擬瀏覽器訪問服務器 # resp = urllib.request.urlopen(request)# handler build_opener openproxies = {'http':'202.55.5.209:8090' }handler = urllib.request.ProxyHandler(proxies=proxies)opener = urllib.request.build_opener(handler)resp = opener.open(request)# 獲取響應信息 content = resp.read().decode("utf-8")# 保存 with open("demo/daili.html",'w',encoding="utf-8") as fp:fp.write(content)fp.close()12.代理池
import urllib.requestproxies_pool= [{'http':'202.55.5.209:8091111','http':'202.55.5.209:8092222'} ] import random proxies = random.choice(proxies_pool) print(proxies)url = "https://www.baidu.com/s?wd=ip"headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ''Safari/537.36', } # 定制請求對象 request = urllib.request.Request(url=url,headers=headers)# ProxyHandler build_opener open handler = urllib.request.ProxyHandler(proxies=proxies) opener = urllib.request.build_opener(handler) resp = opener.open(request)content = resp.read().decode("utf-8") print(content)21.xpath
1.xpath基本使用
# xpath解析 # (1) 本地文件 etree.parse # (2)服務器響應的數據 resp.read().decode("utf-8")**** 使用居多 etree.HTML()-
安裝lxml庫
pip install lxml ‐i https://pypi.douban.com/simple # 如果沒用就換以下 pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python -
導入lxml.etree
from lxml import etree -
etree.parse() 解析本地文件
html頁面
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"/><title>Title</title> </head> <body><ul><li id="l1" class="c1">武漢</li><li id="l2">北京</li><li id="c3">上海</li><li id="c4">深圳</li></ul><ul><li>遼寧</li><li>山西</li><li>重慶</li></ul> </body> </html> # xpath解析本地文件 tree = etree.parse("040_解析_xpath的基本使用.html") # print(tree)# tree.xpath("xpath路徑")# 查找ul下面的li # li_list = tree.xpath("//ul/li")# 查找所有有id屬性的id # li_list = tree.xpath("//ul/li[@id]")# 查找id為l1的li標簽 注意引號的問題 # li_list = tree.xpath("//ul/li[@id='l1']")# 查找到id為l1的li標簽的class屬性值 # li_list = tree.xpath("//ul/li[@id='l1']/@class") # ['c1']# 查詢id中包含l的li標簽 # li_list = tree.xpath("//ul/li[contains(@id,'l')]/text()") # ['武漢', '北京']# 查詢id的值以l開頭的li標簽 # li_list = tree.xpath("//ul/li[starts-with(@id,'l')]/text()") # ['武漢', '北京']# 查詢id為l1和class為c1 # li_list = tree.xpath("//ul/li[@id='l1' and @class='c1']/text()") # ['武漢']# 查詢id為l1或id為l2 li_list = tree.xpath("//ul/li[@id='l1' or @id='l2' ]/text()") # ['武漢', '北京']print(li_list) print(len(li_list)) -
etree.HTML() 服務器響應文件
在瀏覽器上打開xpath: ctrl+shift+x
獲取百度中百度一下
html_tree = etree.HTML(response.read().decode('utf‐8')# (1) 獲取網頁的源碼 # (2) 解析 解析服務器響應的文件 etree.HTML # (3) 打印import urllib.request from lxml import etreeurl = "https://www.baidu.com/"headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ''Safari/537.36', }# 請求對象的定制 request = urllib.request.Request(url=url,headers=headers)# 模擬瀏覽器訪問服務器 resp = urllib.request.urlopen(request)# 獲取網頁源碼 content = resp.read().decode("utf-8")# print(content)# 解析服務器響應的文件 xpath的返回值是一個列表類型的返回值 tree = etree.HTML(content) result = tree.xpath("//input[@id='su']/@value") print(result)
2.抓取站長素材圖片案例
# (1)請求對象的定制 # (2)獲取網頁源碼 # (3)下載# 需求:下載前十頁的圖片 # https://sc.chinaz.com/tupian/fengjingtupian.html 第一頁地址 # https://sc.chinaz.com/tupian/fengjingtupian_2.html 第二頁地址 import urllib.request from lxml import etreedef create_request(page):if (page == 1):url = "https://sc.chinaz.com/tupian/fengjingtupian.html"else:url = "https://sc.chinaz.com/tupian/fengjingtupian_" + str(page + 1) + ".html"headers = {'Cookie': 'UM_distinctid=180329fba793b3-012dea3615a8f7-1734337f-1fa400-180329fba7ae91; ''Hm_lvt_398913ed58c9e7dfe9695953fb7b6799=1657797106; ''Hm_lpvt_398913ed58c9e7dfe9695953fb7b6799=1657797286','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/103.0.0.0 Safari/537.36',}request = urllib.request.Request(url=url,headers=headers)return requestdef get_content(request):response = urllib.request.urlopen(request)content = response.read().decode("utf-8")return contentdef download_photo(content):# 下載圖片tree = etree.HTML(content)name_list = tree.xpath("//div[@id = 'container']//a/img/@alt")# 一般設計圖片的網站都會進行懶加載img_list = tree.xpath("//div[@id = 'container']//a/img/@src")print(len(name_list),len(img_list))# urllib.request.urlretrieve("圖片地址","文件名字")for i in range(len(name_list)):name = name_list[i]src = img_list[i]url = 'https:'+ srcurllib.request.urlretrieve(url=url,filename='demo/zhanzhang/'+name+'.jpg')if __name__ == '__main__':start_page = int(input("請輸入起始頁碼:"))end_page = int(input("請輸入結束頁碼:"))for page in range(start_page, end_page + 1):# (1)請求對象的定制request = create_request(page)# (2)獲取網頁源碼content = get_content(request)# (3)下載源碼download_photo(content)22.JsonPath
pip安裝
pip install jsonpathjsonpath的使用
obj = json.load(open('json文件', 'r', encoding='utf‐8')) ret = jsonpath.jsonpath(obj, 'jsonpath語法')jsonpath與lxml語法對比
數據源
{ "store": {"book": [ { "category": "reference","author": "Nigel Rees","title": "Sayings of the Century","price": 8.95},{ "category": "fiction","author": "Evelyn Waugh","title": "Sword of Honour","price": 12.99},{ "category": "fiction","author": "Herman Melville","title": "Moby Dick","isbn": "0-553-21311-3","price": 8.99},{ "category": "fiction","author": "J. R. R. Tolkien","title": "The Lord of the Rings","isbn": "0-395-19395-8","price": 22.99}],"bicycle": {"color": "red","price": 19.95}} }根據json案例寫出jsonpath解析json數據
import jsonpath import jsonobj = json.load(open("043_解析_jsonpath.json",'r',encoding="utf-8")) # print(obj)# 書店所有書的作者 author_list = jsonpath.jsonpath(obj,'$.store.book[*].author') # print(author_list)# 所有的作者 all_author = jsonpath.jsonpath(obj,'$..author') # print(all_author)# store下面所有的元素 a_list = jsonpath.jsonpath(obj,'$.store.*') # print(a_list)# store里面所有的price p_list = jsonpath.jsonpath(obj,'$.store..price') # print(p_list)# 第三本書 three_b = jsonpath.jsonpath(obj,'$..book[2]') # print(three_b)# 最后一本書 last_b = jsonpath.jsonpath(obj,'$..book[(@.length-1)]') # print(last_b)# 前面兩本書 one_two_book = jsonpath.jsonpath(obj,'$..book[0,1]') # print(one_two_book)# 條件過濾需要在()前面添加一個? # 過濾出所有包含isbn的書 isbn_b = jsonpath.jsonpath(obj,'$..book[?(@.isbn)]') # print(isbn_b)# 過濾出價格低于10的書 low_10_b = jsonpath.jsonpath(obj,'$..book[?(@.price<10)]') print(low_10_b)# 所有元素 all = jsonpath.jsonpath(obj,'$..*') print(all)jsonpath與lxml寫法對比
jsonpath解析淘票票
import json import urllib.request import jsonpathurl = "https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1657803673954_108&jsoncallback=jsonp109&action" \"=cityAction&n_s=new&event_submit_doGetAllRegion=true "headers = {'accept': '*/*',# 'accept-encoding': 'gzip, deflate, br','accept-language': 'zh-CN,zh;q=0.9','cookie': 't=d62feb12ede27bcd90fe3ffe94fcd7b6; cna=IpPWGiQbjAMCAbe/VXNAveQr; ''cookie2=17a771d956232603066efff8888c59de; v=0; _tb_token_=e9be5b5e1b3be; xlly_s=1; ''tfstk=cpJOBFx4f20GG155Ghhh3dwFrgJOaGgARl_0HKiY2MroUjyzEsX2ELHSTfsfzNnd.; ''l=eBrLzoUILDxDBeT3BO5Bhurza779NQdb8rVzaNbMiInca6gPTUHnqNCHHI4J7dtjgt5AGeKPUcfRbdh2kzUg7FGjL77uKtyuJLpp-e1''..; isg=BICAe8v59pOlJIo0Dr70WK-GUQ5SCWTT7VDLXvoS7RtmdSGfox_JYEQLjd21Qxyr','referer': 'https://dianying.taobao.com/','sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"','sec-fetch-dest': 'script','sec-fetch-mode': 'no-cors','sec-fetch-site': 'same-site','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', }# 請求對象的定制 request = urllib.request.Request(url=url,headers=headers)# 模擬瀏覽器向服務器發送請求 resp = urllib.request.urlopen(request)content = resp.read().decode("utf-8")# 字符串切割 content = content.split("(")[1].split(")")[0]# print(content)# with open("demo/taopiaopiao/tpp.json",'w',encoding='utf-8') as fp: # fp.write(content) fp = open("demo/taopiaopiao/tpp.json",'r',encoding='utf-8') obj = json.load(fp) print(obj)region_name = jsonpath.jsonpath(obj,'$..regionName') print(region_name)23.BeatifulSoup
1.基本簡介
2.安裝以及創建
3.節點定位
4.節點信息
本地數據
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"/><title>Title</title> </head> <body> <div><ul><li id="l1">張三</li><li id="l2">李四</li><li>王五</li><a href="" class="a1">張三之家</a><span>哈哈哈哈</span></ul> </div> <a href="" title="a2">李四之家</a><div id="d1"><span>哈哈哈哈</span> </div> <p id="p1" class="p1">呵呵呵</p> </body> </html>bs4的基本使用
from bs4 import BeautifulSoup# 通過解析本地文件 來將bs4的基礎語法進行解析 # 默認打開的文件的編碼格式是gbk 所以在打開文件的時候需要指定編碼 soup = BeautifulSoup(open('045_解析_bs4的基本使用.html',encoding='utf-8'),'lxml')# 根據標簽名查找節點 # print(soup.a) # 找到的是第一個符合條件的數據# attrs獲取標簽的屬性和屬性值 # print(soup.a.attrs)# bs4的一些函數 # (1) find 返回的是第一個符合條件的數據 # print(soup.find('a')) # 找到title標簽為a2的數據 # print(soup.find('a',title='a2')) # 根據class的值找到標簽對象,注意:class要加下劃線 # print(soup.find('a',class_='a1'))# (2) find_all 返回的是列表,并且返回了所有的a標簽 # print(soup.find_all('a'))# 找到所有a標簽和span標簽 如果要獲取的是多個標簽的數據,那么需要在find_all()的參數中添加的是列表的數據 # print(soup.find_all(['a','span']))# limit是查詢前幾個的數據 # print(soup.find_all('li',limit=2)) # print(soup.find_all('li')[1:3])# (3) select(推薦) # select方法返回的是一個列表,并且會返回多個數據 # print(soup.select('a'))# 可以通過.代表class,這種操作叫做類選擇器 # print(soup.select('.a1')) # [<a class="a1" href="">張三之家</a>]# id選擇器 # print(soup.select(("#l1"))) # [<li id="l1">張三</li>]# 屬性選擇器---通過屬性來尋找對應標簽 # 查找到li標簽中有id的標簽 # print(soup.select('li[id]')) # [<li id="l1">張三</li>, <li id="l2">李四</li>]# 查找到li標簽中id=l2的標簽 # print(soup.select('li[id="l2"]')) # [<li id="l2">李四</li>]# 層級選擇器 # 后代選擇器 # 找到div下面的li,空格代表后代 # print(soup.select('div li')) # [<li id="l1">張三</li>, <li id="l2">李四</li>, <li>王五</li>]# 子代選擇器 # 某標簽的第一級子標簽 注意:很多編程語言中,如果不加空格不會輸出內容,在bs4中不會報錯 # print(soup.select('div>ul>li')) # [<li id="l1">張三</li>, <li id="l2">李四</li>, <li>王五</li>]# 找到a標簽和li標簽的所有對象(優點) # print(soup.select('a,li')) # [<li id="l1">張三</li>, <li id="l2">李四</li>, <li>王五</li>, <a class="a1" href="">張三之家</a>, <a href="" title="a2">李四之家</a>]# 節點信息 # 獲取節點內容 # obj = soup.select('#d1')[0] # 如果標簽對象中,只有內容,那么string和get_text()都可以使用 # 如果標簽對象中,除了內容還有標簽,那么string就獲取不到內容,而get_text()是可以獲取數據 # 我們一般情況下,推薦使用get_text() # print(obj.string) # print(obj.get_text())# 節點的屬性 obj = soup.select('#p1')[0] # name是標簽的名字 # print(obj.name)# 將屬性值作為一個字典返回 # print(obj.attrs) # {'id': 'p1', 'class': ['p1']}# 獲取節點的屬性 obj = soup.select('#p1')[0] print(obj.attrs.get('class')) # ['p1'] print(obj.get('class')) # ['p1'] print(obj['class']) # ['p1']bs4爬取星巴克數據
import urllib.requestfrom bs4 import BeautifulSoupurl = 'https://www.starbucks.com.cn/menu/'resp = urllib.request.urlopen(url)content = resp.read().decode("utf-8")soup = BeautifulSoup(content,'lxml')# //ul[@class='grid padded-3 product']//strong/text() name_list = soup.select('ul[class="grid padded-3 product"] strong') # print(name_list) for name in name_list:print(name.get_text())24.Requests
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-t0m1X1Vw-1658307246358)(D:\Desktop\CSDN博客\Python學習.assets\image-20220717110557728.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MndtXWN6-1658307246359)(D:\Desktop\CSDN博客\Python學習.assets\image-20220717110618063.png)]
1.一個方法以及六個屬性
基本使用
import requestsurl = 'http://www.baidu.com'resp = requests.get(url=url)# 一個類型,六個屬性 <class 'requests.models.Response'> # print(type(resp))# 1.設置響應的編碼格式 resp.encoding = 'utf-8'# 2.以字符串形式返回了網頁源碼 # print(resp.text)# 3.返回url地址 # print(resp.url)# 4.返回二進制數據 # print(resp.content)# 5.返回響應的狀態碼 # print(resp.status_code)# 6.獲取響應頭 print(resp.headers)2.requests與urllib的區別
# urllib # (1) 一個類型以及六個方法 # (2) get請求 # (3) post請求 百度翻譯 # (4) ajax的get請求 # (5) ajax的post請求 # (6) cookie登錄 微博 # (7) 代理 快代理# requests # (1) 一個類型以及六個屬性 # (2) get請求 # (3) post請求 # (4) 代理 # (5) cookie 驗證碼3.get請求
import requestsurl = 'https://www.baidu.com/s'headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ""Safari/537.36 " }data = {'wd':'北京' }# url 請求資源路徑 # params 參數 # kwargs 字典 resp = requests.get(url=url,params=data,headers=headers)content = resp.text print(content)# 總結: # 參數使用params傳遞 # 參數無須urlencoding編碼 # 不需要請求對象的定制 # 請求資源路徑中的?可以加也可以不加4.post請求
import jsonimport requestsurl = 'https://fanyi.baidu.com/sug'headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ""Safari/537.36 " }data = {'kw': 'eye' }# url 請求地址 # data 請求參數 # kwargs 字典 resp = requests.post(url=url, data=data, headers=headers)content = resp.text# 轉成json格式 obj = json.loads(content.encode('utf-8')) print(obj)# 總結 # (1) post請求 是不需要編解碼 # (2) post請求的參數是data # (3) 不需要請求對象的定制5.cookie登錄古詩文網
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nbvklSwY-1658307246360)(D:\Desktop\CSDN博客\Python學習.assets\image-20220717121244899.png)]
# 通過登錄 然后進入到主頁面# 通過找登錄接口我們發現,登錄的時候需要的參數很多 # __VIEWSTATE: WQcK5cuI5TJ9JhnptzvgDT7zIWCLYU1DlLMsyTxFVGrXSoTAWWvYxcP1QP96hGeWPO/zIWvqJtAW6wk/Q4nQy9xjvWQZbMzhAsJhgpEJovkoPf4vzXgZSwoMXttI98whqL29O6+E6iocDXxBeF6loWoheEs= # __VIEWSTATEGENERATOR: C93BE1AE # from: http://so.gushiwen.cn/user/collect.aspx # email: 18672599132 # pwd: wwwddddd # code: wrvh # denglu: 登錄# 觀察到__VIEWSTATE __VIEWSTATEGENERATOR code是變量# 難點 :(1)__VIEWSTATE __VIEWSTATEGENERATOR 一般情況看不到的數據 都是在頁面的源碼中 # 我們觀察到的這兩個數據在頁面的源碼中,所以我們需要獲取頁面的源碼,然后進行解析就可以獲取了 # (2) code驗證碼import requests from bs4 import BeautifulSoup# 登錄頁面的url地址 url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 ""Safari/537.36 " } # 獲取頁面源碼 resp = requests.get(url=url,headers=headers) content = resp.text # print(content)# 解析頁面源碼 soup = BeautifulSoup(content,'lxml') # 獲取__VIEWSTATE viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value') # 獲取__VIEWSTATEGENERATOR viewstateGenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')# 獲取驗證碼圖片 code = soup.select('#imgCode')[0].attrs.get('src') code_url = 'https://so.gushiwen.cn'+code# 有坑 獲取驗證碼后相當于向服務器請求一次了,后續登錄時又請求了一次,兩次驗證碼不一致 # import urllib.request # urllib.request.urlretrieve(url=code_url,filename='code.jpg') # requests中有一個方法 session(),通過session返回值就能使用請求變成一個對象 session = requests.session() # 驗證碼的url的內容 resp_code = session.get(code_url) # 注意此時要使用二進制數據,因為我們要使用的是圖片的下載 content_code = resp_code.contentwith open('code.jpg','wb') as fp:fp.write(content_code)fp.close()# 獲取驗證碼的圖片后下載到本地,然后觀察驗證碼,觀察之后在控制臺輸入這個驗證碼,就可以把值給code的參數然后登錄 code_name = input("請輸入你的驗證碼:")# 點擊登錄提交后的url url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'data_post = { '__VIEWSTATE': viewstate, '__VIEWSTATEGENERATOR': viewstateGenerator, 'from': 'http://so.gushiwen.cn/user/collect.aspx', 'email': '18672599132', 'pwd': 'dhn913219642', 'code': code_name, 'denglu': '登錄', } # 不能使用requests.post 必須使用session!!! resp_post = session.post(url=url_post,data=data_post,headers=headers)content_post = resp_post.textwith open('demo/gushiwen/gushiwen.html','w',encoding='utf-8') as fp:fp.write(content_post)fp.close() # 難點 # (1)隱藏域 # (2)驗證碼6.超級鷹打碼平臺的使用
25.scrapy
scrapy是什么?
Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。安裝scrapy
pip install scrapy1.基本使用
1.1創建scrapy項目
終端輸入 scrapy startproject 項目名稱
1.2項目組成
1.3創建爬蟲文件
跳轉到spiders文件夾
cd 目錄名字/目錄名字/spiders創建爬蟲文件.py
scrapy genspider 爬蟲名字 網頁的域名 # 比如 scrapy genspider baidu www.baidu.com爬蟲文件的基本組成
生成的爬蟲文件
import scrapyclass BaiduSpider(scrapy.Spider):# 爬蟲名字,用于運行爬蟲時使用的值name = 'baidu'# 允許訪問的域名allowed_domains = ['www.baidu.com']# 起始的url地址,指的是第一次要訪問的域名# start_urls 是在allowed_domains的前面添加一個http:// 在allowed_domains的后面添加了一個斜線# start_urls的值是根據allowed_domains的基礎上修改出來的start_urls = ['http://www.baidu.com/']# 執行了start_urls之后執行的方法 方法中的response 就是返回的那個對象# 相當于response = urllib.request.ulopen()# 還相當于response = requests.get()def parse(self, response):print('hello scrapy')運行爬蟲代碼
scrapy crawl 爬蟲的名字 eg: scrapy crawl baidu運行后有君子協議,修改君子協議
# 在settings.py中注釋以下 # ROBOTSTXT_OBEY = True1.4 爬取58同城數據
項目結構
scrapy項目的結構項目名字項目名字spiders文件夾(存儲的是爬蟲文件)init自定義的爬蟲文件inititems 定義數據結構的地方,爬取的數據都包含哪些middleware 中間件 代理pipelines 管道 用來處理下載的數據settings 配置文件 robots協議 ua定義等response屬性的方法
response.text 獲取的是響應的字符串 response.body 獲取的是二進制數據 response.xpath 可以直接是xpath方法來解析response中的內容 response.extract() 提取selector對象的data屬性值 response.extract_first() 提取的是selector列表的第一個數據代碼
import scrapyclass TcSpider(scrapy.Spider):name = 'tc'allowed_domains = ['ty.58.com']start_urls = ['http://ty.58.com/']def parse(self, response):print("=================")# 返回的頁面字符串# content = response.text# 返回的頁面二進制數據# content = response.body# 可以直接使用xpath方法解析response中的內容content = response.xpath("//ul[@class='icoNav']")print(content)1.5 scrapy架構組成
1.6 scrapy工作原理
scrapy爬取汽車之家
import scrapyclass CarSpider(scrapy.Spider):name = 'car'allowed_domains = ['https://car.autohome.com.cn/price/brand-15.html']# 注意如果你的請求是html結尾的,是不需要加/start_urls = ['https://car.autohome.com.cn/price/brand-15.html']def parse(self, response):print("=============")name_list = response.xpath("//div[@class='main-title']/a/text()")price_list = response.xpath("//div[@class='main-lever-right']//span/span/text()")for i in range(len(name_list)):# <Selector xpath="//div[@class='main-title']/a/text()" data='寶馬X3'> 遍歷出來是selector形式 extract()可以提取出數據print(name_list[i].extract(),price_list[i].extract())1.7 scrapy shell
# 進入到scrapy shell的終端,直接在window的終端中輸入scrapy shell 域名 # 如果想看到一些高亮或自動補全,那么可以安裝ipython pip install ipython # scrapy shell www.baidu.com In [3]: response.url Out[3]: 'http://www.baidu.com'In [4]: response.status Out[4]: 200In [5]: response.xpath("//input[@id='su']/@value") Out[5]: [<Selector xpath="//input[@id='su']/@value" data='百度一下'>]In [6]: response.xpath("//input[@id='su']/@value").extract() Out[6]: ['百度一下']In [7]: response.xpath("//input[@id='su']/@value").extract_first() Out[7]: '百度一下'1.8.yield
簡要理解:
yield就是 return 返回一個值,并且記住這個返回的位置,下次迭代就從這個位置后(下一行)開始
案例1:當當網
(1)yield(2)管道封裝(3)多條管道下載 (4)多頁數據下載
實現代碼
dangdang.py
import scrapy from scrapy_dangdang_062.items import ScrapyDangdang062Itemclass DangdangSpider(scrapy.Spider):name = 'dangdang'# 如果要多頁下載的話,那么必須要調整的是allowed_domains的范圍,一般情況下只寫域名allowed_domains = ['category.dangdang.com']start_urls = ['http://category.dangdang.com/cp01.01.01.00.00.00.html']base_url = 'http://category.dangdang.com/pg'page = 1def parse(self, response):print("========")# pipelines 下載數據# items 定義數據結構# src = response.xpath("//ul[@id='component_59']/li/a/img/@src")# name = response.xpath("//ul[@id='component_59']/li/a/img/@alt")# price = response.xpath("//ul[@id='component_59']/li//p[@class='price']/span[1]/text()")# 所有的selector的對象都可以再次調用xpath方法li_list = response.xpath("//ul[@id='component_59']/li")for li in li_list:# 圖片懶加載,所以都是一樣的,第一張圖片和其他圖片不一樣,第一張圖片得使用srcsrc = li.xpath("./a/img/@data-original").extract_first()if src:src = srcelse:src = li.xpath("./a/img/@src").extract_first()name = li.xpath("./a/img/@alt").extract_first()price = li.xpath(".//p[@class='price']/span[1]/text()").extract_first()book = ScrapyDangdang062Item(src=src, name=name, price=price)# print(src,name,price)# 獲取一個book就將book交給pipelines, yield相當于return book# yield是迭代器,將封裝的book交給pipelinesyield book# 每一頁的爬取的業務邏輯全都是一樣的,所以我們只需要將執行的頁的請求再次調用parse方法 # 第一頁:http://category.dangdang.com/cp01.01.01.00.00.00.html # 第二頁:http://category.dangdang.com/pg2-cp01.01.01.00.00.00.html # 第三頁:http://category.dangdang.com/pg3-cp01.01.01.00.00.00.html # 觀察規律if self.page<100:self.page = self.page+1url = self.base_url+str(self.page)+'-cp01.01.01.00.00.00.html'# 怎么去調用parse對象# scrapy.Request就是scrapy的get方法# url就是請求地址# callback就是你要執行的那個函數,注意不要加()yield scrapy.Request(url=url,callback=self.parse)pipelines.py
# Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface from itemadapter import ItemAdapter# 如果想使用管道的話,那么就必須在settings中打開管道(打開注釋) # ITEM_PIPELINES = { # 'scrapy_carhome_060.pipelines.ScrapyCarhome060Pipeline': 300, # } class ScrapyDangdang062Pipeline:# 這樣切片編程減少文件處理量,只用開始打開,后面關閉就可,中間切片寫入數據# 在爬蟲文件開始前執行的方法def open_spider(self,spider):self.fp = open("book.json",'w',encoding='utf-8')# item就是yield后面的bookdef process_item(self, item, spider):# 以下這種模式不推薦,因為每傳遞一個對象,那么就打開一個文件,對文件的操作過于頻繁# 下載數據# (1) write方法必須要寫一個字符串,而不能是其他的對象# (2) w模式,會每一個對象都打開一次文件,覆蓋之前的內容,a可以追加文本# with open("book.json",'a',encoding='utf-8') as fp:# fp.write(str(item))# # fp.close()self.fp.write(str(item))return item# 在爬蟲文件開始后執行的方法def close_spider(self,spider):self.fp.close()import urllib.request # 多條管道開啟 # (1)定義管道類 # (2)在settings中開啟管道(新增一條) # ITEM_PIPELINES = { # 'scrapy_dangdang_062.pipelines.DangDangDownloadPipeline': 301 # } class DangDangDownloadPipeline:def process_item(self, item, spider):url = 'http:'+item.get('src')filename = './book/book'+item.get('name')+'.jpg'urllib.request.urlretrieve(url=url,filename=filename)return itemitems.py
# Define here the models for your scraped items # # See documentation in: # https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapy# 定義數據結構 class ScrapyDangdang062Item(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()# 通俗的說就是你要下載的數據都有什么# 圖片src = scrapy.Field()# 圖書名name = scrapy.Field()# 價格price = scrapy.Field()settings.py
ITEM_PIPELINES = {'scrapy_dangdang_062.pipelines.ScrapyDangdang062Pipeline': 300,'scrapy_dangdang_062.pipelines.DangDangDownloadPipeline': 301 }案例2:電影天堂
mv.py
# Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface import urllib.requestfrom itemadapter import ItemAdapterclass ScrapyMovie063Pipeline:def open_spider(self,spider):self.fp = open('movie.json','w',encoding='utf-8')def process_item(self, item, spider):self.fp.write(str(item))# 下載圖片url = item.get('src')filename = './movies/'+str(item.get('name'))+'.jpg'urllib.request.urlretrieve(url=url,filename=filename)return itemdef close_spider(self, spider):self.fp.close()items.py
# Define here the models for your scraped items # # See documentation in: # https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass ScrapyMovie063Item(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()name = scrapy.Field()src = scrapy.Field()pipelines.py
# Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface import urllib.requestfrom itemadapter import ItemAdapterclass ScrapyMovie063Pipeline:def open_spider(self,spider):self.fp = open('movie.json','w',encoding='utf-8')def process_item(self, item, spider):self.fp.write(str(item))# 下載圖片url = item.get('src')filename = './movies/'+str(item.get('name'))+'.jpg'urllib.request.urlretrieve(url=url,filename=filename)return itemdef close_spider(self, spider):self.fp.close()1.9 CrawlSpider
鏈接提取器,繼承自scrapy.Spider
- 獨門秘笈
CrawlSpider可以定義規則,再解析html內容的時候,可以根據鏈接規則提取出指定的鏈接,然后再向這些鏈接發送請求
所以,如果有需要跟進鏈接的需求,意思就是爬取了網頁之后,需要提取鏈接再次爬取,使用CrawlSpider是非常合適的 - 提取鏈接
模擬使用
- 提取連接
注意事項
【注1】callback只能寫函數名字符串,不需要寫圈函數帶上(), callback=‘parse_item’
【注2】在基本的spider中,如果重新發送請求,那里的callback寫的是callback=self.parse_item
【注‐‐稍后看】follow=true 是否跟進 就是按照提取連接規則進行提取
運行原理
crawlSpider案例
需求:讀書網數據入庫
創建項目
scrapy startproject scrapy_readbook_064創建爬蟲類
scrapy genspider -t crawl read https://www.dushu.com/book/1090.html實現代碼
read.py
import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rulefrom scrapy_readbook_064.items import ScrapyReadbook064Itemclass ReadSpider(CrawlSpider):name = 'read'allowed_domains = ['www.dushu.com']start_urls = ['https://www.dushu.com/book/1188.html']rules = (# \是轉義符,\d是數字占位符Rule(LinkExtractor(allow=r'/book/1188_\d+\.html'),callback='parse_item',follow=False),)def parse_item(self, response):item = {}print("================")img_list = response.xpath("//div[@class='bookslist']//img")for img in img_list:name = img.xpath("./@alt").extract_first()src = img.xpath('./@data-original').extract_first()book = ScrapyReadbook064Item(name=name,src=src)yield bookreturn itemitems.py
# Define here the models for your scraped items # # See documentation in: # https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass ScrapyReadbook064Item(scrapy.Item):# define the fields for your item here like:name = scrapy.Field()src = scrapy.Field()passpipelines.py
# Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface from itemadapter import ItemAdapterclass ScrapyReadbook064Pipeline:def open_spider(self,spider):self.fp = open('book.json','w',encoding='utf-8')def process_item(self, item, spider):self.fp.write(str(item))return itemdef close_spider(self,spider):self.fp.close()代碼實現
read.py
import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rulefrom scrapy_readbook_064.items import ScrapyReadbook064Itemclass ReadSpider(CrawlSpider):name = 'read'allowed_domains = ['www.dushu.com']# 第一頁與其他頁不一樣,所以需要_1start_urls = ['https://www.dushu.com/book/1188_1.html']rules = (# \是轉義符,\d是數字占位符Rule(LinkExtractor(allow=r'/book/1188_\d+\.html'),callback='parse_item',# follow=True是否跟進,就三種提取連接規則進行提取follow=True),)def parse_item(self, response):item = {}print("================")img_list = response.xpath("//div[@class='bookslist']//img")for img in img_list:name = img.xpath("./@alt").extract_first()src = img.xpath('./@data-original').extract_first()book = ScrapyReadbook064Item(name=name,src=src)yield bookreturn itemsettings.py
DB_HOST = 'localhost' # 端口號是一個整數 DB_PORT = 3306 DB_USER = 'root' DB_PASSWORD = '123456' DB_NAME = 'spider01' # utf-8的杠不允許寫 DB_CHARSET = 'utf8'ITEM_PIPELINES = {'scrapy_readbook_064.pipelines.ScrapyReadbook064Pipeline': 300,"scrapy_readbook_064.pipelines.MysqlPipeline" : 301 }pipelines.py
# Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface from itemadapter import ItemAdapterclass ScrapyReadbook064Pipeline:def open_spider(self,spider):self.fp = open('book.json','w',encoding='utf-8')def process_item(self, item, spider):self.fp.write(str(item))return itemdef close_spider(self,spider):self.fp.close()# 加載settings文件 from scrapy.utils.project import get_project_settings # 導入pymysql import pymysqlclass MysqlPipeline:def open_spider(self,spider):settings = get_project_settings()self.host = settings['DB_HOST']self.port = settings['DB_PORT']self.user = settings['DB_USER']self.password = settings['DB_PASSWORD']self.name = settings['DB_NAME']self.charset = settings['DB_CHARSET']self.connect()def connect(self):self.conn = pymysql.connect(host=self.host,port=self.port,user=self.user,password=self.password,db=self.name,charset=self.charset)self.cursor = self.conn.cursor()def process_item(self, item, spider):sql = 'insert into book(name,src) values("{}","{}")'.format(item['name'],item['src'])# 執行sql語句self.cursor.execute(sql)self.conn.commit()return itemdef close_spider(self,spider):self.cursor.close()self.conn.close()items.py
# Define here the models for your scraped items # # See documentation in: # https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass ScrapyReadbook064Item(scrapy.Item):# define the fields for your item here like:name = scrapy.Field()src = scrapy.Field()pass1.10 日志信息以及日志級別
# 指定日志級別 LOG_LEVEL = 'WARNING' # 會給出日志文件 LOG_FILE = 'logdemo.log'總結
以上是生活随笔為你收集整理的Python基础学习--基于尚硅谷python教学视频的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 萨缪尔森微观经济学第19版真题和课后答案
- 下一篇: 推荐一份完整的python教学视频