網(wǎng)絡(luò)爬蟲開發(fā)
pip install requests lxml beautifulsoup4 selenium pandas matplotlib fake_useragent tqdm openpyxl
初識(shí)爬蟲
1.requests請(qǐng)求庫(kù)模塊
Pycharm終端安裝requests請(qǐng)求庫(kù)
pip install requests
①.導(dǎo)入requests請(qǐng)求庫(kù)
import requests
②.定義個(gè)變量要抓取的頁(yè)面:
url = '網(wǎng)址'
③.構(gòu)造請(qǐng)求頭(偽裝身份user-agent)
打開要抓取的網(wǎng)址,快捷鍵:F12→Network(網(wǎng)絡(luò))→Name(名稱)→點(diǎn)一個(gè)文件→Header(標(biāo)頭)→user-agent(拉到底部就會(huì)看到)



#偽裝成瀏覽器的身份進(jìn)行抓取 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' }
④.發(fā)起請(qǐng)求并接收響應(yīng)對(duì)象
response = requests.get(url = url, headers = headers) encoding = 'utf-8'
bd_url = 'https://www.baidu.com/' # 定義要請(qǐng)求的url數(shù)據(jù)包 response = requests.get(url=bd_url) # 發(fā)起請(qǐng)求并且接收響應(yīng)對(duì)象 response.encoding = 'utf-8' # 設(shè)置編碼格式 print(response) # <Response [200]> 響應(yīng)對(duì)象 print(response.text) # 獲取文本內(nèi)容 print(response.content) # 獲取到進(jìn)制格式的數(shù)據(jù) print(response.headers) # 獲取響應(yīng)頭信息 print(response.request.headers) # 獲取請(qǐng)求頭信息 print(response.status_code) # 獲取狀態(tài)碼 print(response.encoding) # 獲取當(dāng)前編碼格式 print(response.url) # 獲取到當(dāng)前請(qǐng)求的url print(response.cookies) # 獲取到用戶身份對(duì)象 print(response.content.decode()) # .decode() 默認(rèn)utf-8 進(jìn)行解碼 如果需要使用其他編碼進(jìn)行解碼 傳參即可
⑤.保存文件然后讀取
#完整示例-爬圖 import requests url = 'https://pic.netbian.com/uploads/allimg/240924/081942-17271371826661.jpg' response = requests.get(url=url) # print(response.content) with open('王楚然.jpg', 'wb') as f: f.write(response.content) #完整示例-爬音頻 import requests url = 'https://m701.music.126.net/20240924221116/8ec6067b2ae956d58df4deff0bdddaf9/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/31433228192/7100/62f1/fd29/3833d333ff983ce8eebe35872a9484ee.m4a' response = requests.get(url=url) with open('大人中.mp3', 'wb') as f: f.write(response.content) #爬視頻 import requests cookies = { 'PEAR_UUID': '7b913605-1037-4a28-b16a-46e7657e6f03', 'Hm_lvt_9707bc8d5f6bba210e7218b8496f076a': '1727185861', 'HMACCOUNT': '33EE743B756BCDEE', 'Hm_lpvt_9707bc8d5f6bba210e7218b8496f076a': '1727185870', } headers = { 'accept': '*/*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', # 'cookie': 'PEAR_UUID=7b913605-1037-4a28-b16a-46e7657e6f03; Hm_lvt_9707bc8d5f6bba210e7218b8496f076a=1727185861; HMACCOUNT=33EE743B756BCDEE; Hm_lpvt_9707bc8d5f6bba210e7218b8496f076a=1727185870', 'pragma': 'no-cache', 'priority': 'i', 'range': 'bytes=0-', 'referer': 'https://www.pearvideo.com/', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'video', '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/129.0.0.0 Safari/537.36', } response = requests.get( 'https://video.pearvideo.com/mp4/short/20171004/cont-1165391-10964201-hd.mp4', cookies=cookies, headers=headers, ) print(response.content) with open('1.mp4', 'wb') as f: f.write(response.content)
Pycharm內(nèi)置模塊方法(不推薦使用)
from urllib.request import urlopen url ='url'#要爬取的數(shù)據(jù)網(wǎng)頁(yè) html = urlopen(url) #print(html.read().decode('utf-8')) with open("爬取的文件.html", "w",encoding="utf-8") as f: write = f.write(html.read().decode('utf-8'))
★用input方法的get請(qǐng)求
import requests from urllib.parse import quote import time try: # 獲取用戶輸入并進(jìn)行URL編碼 content = input("請(qǐng)輸入你要查詢的內(nèi)容:") encoded_content = quote(content) # 構(gòu)建請(qǐng)求URL url = f"https://www.sogou.com/web?query={encoded_content}" # 設(shè)置請(qǐng)求頭模擬瀏覽器 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" } # 發(fā)送HTTP請(qǐng)求 print(f"正在請(qǐng)求: {url}") resp = requests.get(url, headers=headers, timeout=10) # 設(shè)置超時(shí)時(shí)間 # 檢查響應(yīng)狀態(tài)碼 resp.raise_for_status() # 若狀態(tài)碼非200,拋出HTTPError # 保存響應(yīng)內(nèi)容到文件 filename = f"爬取的{content[:10]}內(nèi)容.html" # 文件名包含部分查詢內(nèi)容 with open(filename, "w", encoding="utf-8") as f: f.write(resp.text) # 直接使用resp.text print(f"? 文件已成功保存為: {filename}") print(f"狀態(tài)碼: {resp.status_code}") except requests.exceptions.HTTPError as e: print(f"HTTP請(qǐng)求錯(cuò)誤: {e}") except requests.exceptions.Timeout: print("請(qǐng)求超時(shí),請(qǐng)重試") except requests.exceptions.RequestException as e: print(f"網(wǎng)絡(luò)請(qǐng)求異常: {e}") except Exception as e: print(f"發(fā)生未知錯(cuò)誤: {e}") finally: # 控制請(qǐng)求頻率 time.sleep(1) # 等待1秒后結(jié)束程序
★用input方法的post請(qǐng)求
import requests from urllib.parse import urlencode import time import json try: # 獲取用戶輸入 keyword = input("請(qǐng)輸入你要翻譯的內(nèi)容:") # 百度翻譯API的POST接口 url = "https://fanyi.baidu.com/sug" # 設(shè)置請(qǐng)求頭 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Content-Type": "application/x-www-form-urlencoded" } # 構(gòu)建POST請(qǐng)求的表單數(shù)據(jù)(百度翻譯API需要的參數(shù)) data = { "kw": keyword # 百度翻譯API使用'kw'參數(shù)傳遞要翻譯的內(nèi)容 } # 發(fā)送POST請(qǐng)求 print(f"正在請(qǐng)求: {url}") resp = requests.post(url, headers=headers, data=data, timeout=10) #發(fā)送post請(qǐng)求時(shí),傳參數(shù)用的是data. # 檢查響應(yīng)狀態(tài)碼 resp.raise_for_status() # 解析JSON響應(yīng) result = resp.json() # 保存響應(yīng)內(nèi)容到文件 filename = f"翻譯結(jié)果_{keyword[:10]}.json" with open(filename, "w", encoding="utf-8") as f: json.dump(result, f, ensure_ascii=False, indent=2) print(f"? 翻譯結(jié)果已保存為: {filename}") print(f"狀態(tài)碼: {resp.status_code}") # 簡(jiǎn)單打印翻譯結(jié)果 if result.get('errno') == 0 and 'data' in result: print("\n翻譯結(jié)果預(yù)覽:") for item in result['data'][:3]: # 只顯示前3個(gè)結(jié)果 print(f"{item.get('k', '')} -> {item.get('v', '')}") except requests.exceptions.HTTPError as e: print(f"HTTP請(qǐng)求錯(cuò)誤: {e}") except requests.exceptions.Timeout: print("請(qǐng)求超時(shí),請(qǐng)重試") except requests.exceptions.RequestException as e: print(f"網(wǎng)絡(luò)請(qǐng)求異常: {e}") except json.JSONDecodeError: print("無(wú)法解析JSON響應(yīng),可能是請(qǐng)求格式不正確") except Exception as e: print(f"發(fā)生未知錯(cuò)誤: {e}") finally: # 控制請(qǐng)求頻率 time.sleep(1)
參數(shù)請(qǐng)求與Cookie



import requests url = "https://movie.douban.com/j/chart/top_list" #問(wèn)號(hào)后面的參數(shù)可以用字典的形式傳參數(shù) data = { "type":"13", "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/137.0.0.0 Safari/537.36", "Content-Type": "application/x-www-form-urlencoded" } response = requests.get(url, params=data, headers=headers)#發(fā)送get請(qǐng)求時(shí),傳參數(shù)用的是params print(response.json())
在編程語(yǔ)言中使用 XPath
pycharm終端安裝lxml庫(kù):
pip install lxml #或使用鏡像下載安裝 pip install lxml -i 鏡像地址
pycharm終端查看當(dāng)前環(huán)境下安裝了哪些庫(kù)
pip list
①.解析 XML 文檔
2.2.etree.fromstring():可以將 XML/HTML 格式的字符串解析為樹形結(jié)構(gòu)(ElementTree 對(duì)象),以便于后續(xù)的遍歷、查詢和修改。
from lxml import etree xml_str = '<book><title>Python編程</title><price>99.0</price></book>' root = etree.fromstring(xml_str) # 獲取根節(jié)點(diǎn)標(biāo)簽 print(root.tag) # 輸出: book # 查找子節(jié)點(diǎn) title = root.find('title').text price = root.find('price').text print(f"書名: {title}, 價(jià)格: {price}") # 輸出: 書名: Python編程, 價(jià)格: 99.0
②.遍歷元素
# 遍歷所有子元素 for child in root: print(child.tag, child.text) # 輸出: element 內(nèi)容 # 使用XPath查找元素 elements = root.xpath('//element')
# 創(chuàng)建新元素 new_element = etree.Element('new_element') new_element.text = '新內(nèi)容' # 添加到根節(jié)點(diǎn) root.append(new_element) # 修改現(xiàn)有元素 root.find('element').text = '更新后的內(nèi)容' # 刪除元素 root.remove(new_element)
④.輸出文檔
# 轉(zhuǎn)換為字符串 xml_output = etree.tostring(root, pretty_print=True, encoding='unicode') print(xml_output) # 寫入文件 # etree.ElementTree(root).write('output.xml', pretty_print=True)
from lxml import etree #如果Pycharm報(bào)錯(cuò)可以考慮下面這種導(dǎo)入方式 from lxml imprt html etree=html.etree html = '<html><body><div class="content"><h1>Hello</h1></div></body></html>' tree = etree.HTML(html) # 選擇所有<h1>元素的文本 titles = tree.xpath('//h1/text()') print(titles) # 輸出: ['Hello'] # 選擇class為"content"的<div>元素 divs = tree.xpath('//div[@class="content"]')
打開抓取的html文檔然后讀取
with open('抓取的文檔.html', 'r', encoding='utf-8') as f: html = f.read() # 讀取 # print(html) # 讀取出來(lái)的文本內(nèi)容 # print(type(html)) # <class 'str'>查看類開,字符串類型 tree = etree.HTML(html) # 渲染html
// 選擇第一個(gè)<h1>元素 const h1 = document.evaluate('//h1', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; // 選擇所有<a>元素的href屬性 const links = document.evaluate('//a/@href', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (let i = 0; i < links.snapshotLength; i++) { console.log(links.snapshotItem(i).value); }
①.基本路徑表達(dá)式
xpath 通過(guò)路徑表達(dá)式從根節(jié)點(diǎn)(/)或當(dāng)前節(jié)點(diǎn)(.)開始定位元素:
xpath方法返回值是列表 xpath語(yǔ)法規(guī)定索引值從1開始
- 絕對(duì)路徑:從根節(jié)點(diǎn)開始,使用
/分隔節(jié)點(diǎn)名稱。
xpath('/html/body/div/h1/') # 選擇HTML文檔中的<h1>元素 xpath('/html/body/div/h1/text()') # 選擇HTML文檔中的<h1>元素的數(shù)據(jù)
- 相對(duì)路徑:從當(dāng)前節(jié)點(diǎn)開始,使用
//表示任意層級(jí)的子節(jié)點(diǎn)。
xpath('//div/p') # 選擇所有<div>下的<p>元素(不限層級(jí))
| 符號(hào) | 作用 |
| // | 從任意位置開始選擇節(jié)點(diǎn)。 |
| . | 選擇當(dāng)前節(jié)點(diǎn)。 |
| .. | 選擇當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。 |
| @ | 選擇屬性。 |
| * | 通配符,匹配任意節(jié)點(diǎn)或?qū)傩?/td> |
| [ ] | 條件表達(dá)式,用于篩選節(jié)點(diǎn)。 |
| position | 當(dāng)前節(jié)點(diǎn)的位置(如 [1] 表示第一個(gè)匹配的節(jié)點(diǎn))。 |
③.常用函數(shù)
- 文本匹配:
xpath('//div[text()="Hello World"]') # 選擇文本內(nèi)容為"Hello World"的<div>
xpath('//div[contains(text(), "World")]') # 選擇包含"World"的<div>
屬性匹配:
xpath('//a[@) # 選擇href屬性為指定值的<a>標(biāo)簽
xpath('//input[@type="text"]') # 選擇包含"World"的<div>
位置篩選:
xpath('//li[position()=1]') # 選擇第一個(gè)<li>
xpath('//li[last()]') # 選擇最后一個(gè)<li>.<li>
使用 and、or、not() 組合條件:
xpath('//div[@class="container" and @id="main"]') # 同時(shí)滿足兩個(gè)屬性條件
xpath('//div[@class="item" or @class="product"] ') # 滿足任一屬性條件
xpath('//div[not(@class="ignore")]') # 排除特定屬性的<div>
軸用于選擇當(dāng)前節(jié)點(diǎn)的相關(guān)節(jié)點(diǎn)(如父節(jié)點(diǎn)、兄弟節(jié)點(diǎn)等):
| 軸名稱 | 作用 | 示例 |
| parent:: | 父節(jié)點(diǎn) | xpath('//h1/parent::div') |
| child:: | 子節(jié)點(diǎn)(默認(rèn)) | xpath('//div/child::p') |
| descendant | 所有后代節(jié)點(diǎn)(不限層級(jí)) | xpath('//div/descendant::span') |
| ancestor:: | 所有祖先節(jié)點(diǎn)(包括父節(jié)點(diǎn)的父節(jié)點(diǎn)) | xpath('//p/ancestor::body') |
| following-sibling:: | 后續(xù)兄弟節(jié)點(diǎn) | xpath('//li[1]/following-sibling::li') |
| preceding-sibling: | 前續(xù)兄弟節(jié)點(diǎn) | xpath('//li[3]/preceding-sibling::li') |
案例:
# 導(dǎo)入所需庫(kù) import requests # 用于發(fā)送HTTP請(qǐng)求,獲取網(wǎng)頁(yè)內(nèi)容 from lxml import etree # 用于解析HTML文檔,提取需要的信息 # 定義基本參數(shù) # 目標(biāo)網(wǎng)頁(yè)URL(小說(shuō)章節(jié)頁(yè)面) url = 'https://www.xs386.com/6661/32866513.html' # 請(qǐng)求頭信息,模擬瀏覽器訪問(wèn) headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' } # user-agent用于告訴服務(wù)器訪問(wèn)者的瀏覽器信息,避免被服務(wù)器識(shí)別為爬蟲而拒絕訪問(wèn)。 # 發(fā)送GET請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容 response = requests.get(url=url, headers=headers) # 設(shè)置正確的編碼,設(shè)置編碼為utf-8,確保中文顯示正常 response.encoding = 'utf-8' # 將HTML文本解析為可操作的元素樹對(duì)象 e = etree.HTML(response.text) # 將網(wǎng)頁(yè)源代碼轉(zhuǎn)換為解析樹,便于后續(xù)提取數(shù)據(jù) # 使用XPath表達(dá)式提取id為"content"的div內(nèi)的所有文本,注意返回的是列表 content_list = e.xpath('//div[@id="content"]//text()') # 查找整個(gè)文檔中 id 屬性為 "content" 的 div 元素并提取該 div 下所有層級(jí)的文本內(nèi)容 # 判斷是否成功提取到內(nèi)容 if content_list: # 將列表內(nèi)容合并為字符串 content = '\n'.join(content_list) # 清理內(nèi)容中的多余空格和換行 content = content.strip() # 保存到文件(使用utf-8編碼) with open('上門龍婿.txt', 'w', encoding='utf-8') as f: f.write(content) print("內(nèi)容保存成功") else: print("未找到指定內(nèi)容")
3.JSON(JavaScript Object Notation)是一種輕量級(jí)的數(shù)據(jù)交換格式,以易于人閱讀和編寫的文本格式存儲(chǔ)和表示數(shù)據(jù),同時(shí)也易于機(jī)器解析和生成,在前后端數(shù)據(jù)交互、配置文件等場(chǎng)景中被廣泛使用。
- 輕量級(jí):相比 XML 等格式,JSON 的數(shù)據(jù)結(jié)構(gòu)更簡(jiǎn)潔,文件體積更小,傳輸效率更高。
- 跨語(yǔ)言兼容:幾乎所有編程語(yǔ)言都支持 JSON 的解析和生成,便于不同系統(tǒng)間的數(shù)據(jù)交互。
- 可讀性強(qiáng):采用鍵值對(duì)(key-value)結(jié)構(gòu),格式清晰,易于理解和維護(hù)。
- 結(jié)構(gòu)靈活:支持嵌套對(duì)象和數(shù)組,能表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
數(shù)據(jù)類型與表示
- 對(duì)象(Object):用
{}包裹,由鍵值對(duì)組成,鍵和值用:分隔,多個(gè)鍵值對(duì)用,分隔。 - 數(shù)組(Array):用
[]包裹,元素可以是任意數(shù)據(jù)類型,元素間用,分隔。 - 鍵值對(duì):鍵必須是字符串,值可以是字符串、數(shù)字、布爾值、null、對(duì)象或數(shù)組。
{ "id": 1001, "hobbies": ["閱讀", "編程"], "isStudent": false, "address": null }
格式要求
- 鍵名必須用雙引號(hào)
""包裹(部分語(yǔ)言支持單引號(hào),但標(biāo)準(zhǔn) JSON 要求雙引號(hào))。 - 逗號(hào)分隔時(shí),最后一個(gè)鍵值對(duì)后不能有多余的逗號(hào)(部分環(huán)境支持,但可能導(dǎo)致兼容性問(wèn)題)。
// 示例:JSON與JavaScript對(duì)象的轉(zhuǎn)換 const jsonStr = '{"name":"張三","age":25}'; const obj = JSON.parse(jsonStr); // 轉(zhuǎn)換為對(duì)象 console.log(obj.name); // 輸出:張三 const data = { city: "北京", population: 2100 }; const jsonData = JSON.stringify(data); // 轉(zhuǎn)換為JSON字符串 console.log(jsonData); // 輸出:{"city":"北京","population":2100}
- 前后端數(shù)據(jù)交互:Web 應(yīng)用中,前端通過(guò) API 請(qǐng)求從服務(wù)器獲取 JSON 數(shù)據(jù),或向服務(wù)器發(fā)送 JSON 格式的請(qǐng)求參數(shù)。
- 配置文件:如項(xiàng)目配置文件(
package.json)、系統(tǒng)配置等,用 JSON 存儲(chǔ)結(jié)構(gòu)化配置信息。 - 數(shù)據(jù)存儲(chǔ):NoSQL 數(shù)據(jù)庫(kù)(如 MongoDB)支持 JSON 格式的文檔存儲(chǔ),部分關(guān)系型數(shù)據(jù)庫(kù)也支持 JSON 字段。
- API 接口規(guī)范:RESTful API 通常以 JSON 作為數(shù)據(jù)交換格式,例如 OpenAPI(Swagger)規(guī)范。
3.1.json.dump():用于將 Python 對(duì)象(如字典、列表)轉(zhuǎn)換為 JSON 格式的字符串,并將其寫入文件或類文件對(duì)象(如網(wǎng)絡(luò)連接、內(nèi)存緩沖區(qū)等)。這一過(guò)程也被稱為序列化(Serialization)。
json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
參數(shù)說(shuō)明:
obj:需要序列化的 Python 對(duì)象(如字典、列表)。fp:文件對(duì)象(如open('data.json', 'w')返回的對(duì)象),用于寫入 JSON 數(shù)據(jù)。indent:可選參數(shù),指定縮進(jìn)空格數(shù),用于美化 JSON 格式(如indent=2)。ensure_ascii:是否確保所有非 ASCII 字符被轉(zhuǎn)義(默認(rèn)True,中文會(huì)被轉(zhuǎn)義為\uXXXX)。sort_keys:是否按字典鍵排序(默認(rèn)False)。
import json data = { "name": "張三", "age": 30, "hobbies": ["閱讀", "編程"], "address": {"city": "北京", "zipcode": "100000"} } # 將數(shù)據(jù)寫入JSON文件 with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)
若需將 JSON 數(shù)據(jù)打印到控制臺(tái)或日志中,可結(jié)合sys.stdout使用:
import json import sys data = {"code": 200, "message": "操作成功", "data": [1, 2, 3]} json.dump(data, sys.stdout, ensure_ascii=False, indent=2) # 輸出結(jié)果: '''{ "code": 200, "message": "操作成功", "data": [ 1, 2, 3 ] }'''
3.2.json.dumps():用于將 Python 對(duì)象(如字典、列表)轉(zhuǎn)換為 JSON 格式的字符串。這一過(guò)程也被稱為序列化(Serialization)。與json.dump()(寫入文件)不同,json.dumps()返回字符串,適用于網(wǎng)絡(luò)傳輸、打印輸出或內(nèi)存處理。
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
import json data = { "name": "張三", "age": 30, "hobbies": ["閱讀", "編程"], "is_student": False, "address": {"city": "北京", "zipcode": "100000"} } # 將Python對(duì)象轉(zhuǎn)換為JSON字符串 json_str = json.dumps(data, ensure_ascii=False, indent=2) print(json_str)
輸出結(jié)果
{ "name": "張三", "age": 30, "hobbies": ["閱讀", "編程"], "is_student": false, "address": { "city": "北京", "zipcode": "100000" } }
在 API 接口或網(wǎng)絡(luò)通信中,常將數(shù)據(jù)序列化為 JSON 字符串后發(fā)送:
import requests import json data = {"user_id": 123, "action": "login"} json_payload = json.dumps(data) try: response = requests.post( "https://api.example.com/user", # 替換為實(shí)際API地址 data=json_payload, headers={"Content-Type": "application/json"} ) response.raise_for_status() # 檢查請(qǐng)求是否成功(狀態(tài)碼200) except requests.exceptions.ConnectionError as e: print(f"網(wǎng)絡(luò)連接錯(cuò)誤: {e}") print("請(qǐng)檢查域名是否正確、網(wǎng)絡(luò)是否正常連接。") except requests.exceptions.Timeout: print("請(qǐng)求超時(shí),請(qǐng)稍后重試。") except requests.exceptions.HTTPError as e: print(f"HTTP錯(cuò)誤: {e}") except requests.exceptions.RequestException as e: print(f"請(qǐng)求發(fā)生異常: {e}") else: print("請(qǐng)求成功!") print(response.json()) # 處理響應(yīng)數(shù)據(jù)
| 函數(shù)名 | 功能描述 |
| json.dumps() | 將 Python 對(duì)象序列化為字符串(返回值為字符串,適用于網(wǎng)絡(luò)傳輸)。 |
| json.dump() | 將 Python 對(duì)象序列化并寫入文件(需傳入文件對(duì)象,如open('data.json', 'w'))。 |
| json.loads() | 將 JSON 字符串反序列化為 Python 對(duì)象(解析字符串)。 |
| json.load() | 從文件中讀取 JSON 數(shù)據(jù)并反序列化為 Python 對(duì)象。 |
4.re正則表達(dá)式數(shù)據(jù)解析(Regular Expression,簡(jiǎn)稱 Regex 或 RE)是一種強(qiáng)大的文本模式匹配工具,用于在字符串中查找、提取或替換符合特定模式的文本片段。正則表達(dá)式數(shù)據(jù)解析就是利用這種模式匹配能力,從復(fù)雜的文本數(shù)據(jù)中提取出結(jié)構(gòu)化的信息。
- 文本提取:從網(wǎng)頁(yè)、日志文件、配置文件等非結(jié)構(gòu)化文本中提取特定信息
- 數(shù)據(jù)驗(yàn)證:檢查輸入數(shù)據(jù)是否符合特定格式(如郵箱、URL、電話號(hào)碼)
- 文本替換:根據(jù)特定模式批量替換文本內(nèi)容
- 字符串分割:根據(jù)特定分隔符將字符串分割成多個(gè)部分
- 日志分析:從系統(tǒng)日志中提取關(guān)鍵信息(如時(shí)間戳、錯(cuò)誤代碼)
import re
- 普通字符:匹配自身,如
a匹配字符 "a" - 元字符:具有特殊含義的字符,如
.匹配任意字符 - 字符類:用
[]表示,匹配方括號(hào)內(nèi)的任意一個(gè)字符,如[abc]匹配 "a"、"b" 或 "c" - 量詞:控制匹配次數(shù),如
*表示 0 次或多次,+表示 1 次或多次,?表示 0 次或 1 次 - 邊界符:如
^表示字符串開始,$表示字符串結(jié)束 - 分組:用
()表示,可以捕獲匹配的內(nèi)容,如(abc)匹配并捕獲 "abc"
①.基本元字符
| 元字符 | 描述 |
. |
匹配除換行符外的任意單個(gè)字符 |
^ |
匹配字符串的開始位置 |
$ |
匹配字符串的結(jié)束位置 |
* |
匹配前面的子表達(dá)式零次或多次 |
+ |
匹配前面的子表達(dá)式一次或多次 |
? |
匹配前面的子表達(dá)式零次或一次 |
{n} |
匹配前面的子表達(dá)式恰好 n 次 |
{n,} |
匹配前面的子表達(dá)式至少 n 次 |
{n,m} |
匹配前面的子表達(dá)式至少 n 次,最多 m 次 |
②.字符類元字符
[] - 定義字符類,匹配方括號(hào)內(nèi)的任意一個(gè)字符
- 例如:
[abc]匹配 'a'、'b' 或 'c' - 可以使用連字符表示范圍:
[a-z]匹配任意小寫字母 - 開頭使用
^表示取反:[^0-9]匹配任意非數(shù)字字符
| 特殊字符 | 描述 |
\d |
匹配任意數(shù)字,等價(jià)于 [0-9] |
\D |
匹配任意非數(shù)字,等價(jià)于 [^0-9] |
\w |
匹配任意字母、數(shù)字或下劃線,等價(jià)于 [a-zA-Z0-9_] |
\W |
匹配任意非字母、數(shù)字或下劃線,等價(jià)于 [^a-zA-Z0-9_] |
\s |
匹配任意空白字符,包括空格、制表符、換頁(yè)符等 |
\S |
匹配任意非空白字符 |
④.分組和引用
例如:(ab)+ 匹配一個(gè)或多個(gè)連續(xù)的 "ab"
可以捕獲匹配的內(nèi)容,用于后續(xù)引用
例如:(\w+) \1 匹配重復(fù)的單詞,如 "hello hello"
| - 邏輯或,匹配兩個(gè)或多個(gè)模式中的任意一個(gè)
例如:cat|dog 匹配 "cat" 或 "dog"
\ - 轉(zhuǎn)義字符,用于取消元字符的特殊含義
例如:\. 匹配字面意義的點(diǎn)號(hào),也用于表示特殊字符類,如 \d、\s 等
例如:\w+(?=\d) 匹配后面跟數(shù)字的單詞
例如:\w+(?!\d) 匹配后面不跟數(shù)字的單詞
例如:(?<=\$)\d+ 匹配前面是美元符號(hào)的數(shù)字
例如:(?<!\$)\d+ 匹配前面不是美元符號(hào)的數(shù)字
?\b - 匹配單詞邊界,如 \bcat\b 只匹配獨(dú)立的 "cat" 單詞
?\B - 匹配非單詞邊界
?(?:...) - 非捕獲組,分組但不捕獲匹配的內(nèi)容
⑨.貪婪匹配和惰性匹配
貪婪匹配:.* 意思是盡可能多的去匹配結(jié)果
惰性匹配:.*? 意思是盡可能少的去匹配結(jié)果
⑩.常用的正則表達(dá)式格式
re.findall(pattern, string, flags=0)
re.findall()的返回結(jié)果取決于正則表達(dá)式中是否包含捕獲組:
- 無(wú)捕獲組:直接返回所有匹配的子字符串列表
- 有一個(gè)捕獲組:返回每個(gè)匹配中捕獲組的內(nèi)容列表
- 有多個(gè)捕獲組:返回元組列表,每個(gè)元組包含一個(gè)匹配中所有捕獲組的內(nèi)容
import re
# 示例1:無(wú)捕獲組,匹配所有數(shù)字
text1 = "hello 123 world 456"
result1 = re.findall(r'\d+', text1)
print(f"示例1結(jié)果: {result1}") # 輸出: ['123', '456']
# 示例2:有一個(gè)捕獲組,提取所有括號(hào)內(nèi)的內(nèi)容
text2 = "apple (red), banana (yellow), cherry (red)"
result2 = re.findall(r'\((.*?)\)', text2)
print(f"示例2結(jié)果: {result2}") # 輸出: ['red', 'yellow', 'red']
# 示例3:有多個(gè)捕獲組,提取所有水果和顏色
text3 = "apple=red, banana=yellow, cherry=red"
result3 = re.findall(r'(\w+)=(\w+)', text3)
print(f"示例3結(jié)果: {result3}") # 輸出: [('apple', 'red'), ('banana', 'yellow'), ('cherry', 'red')]
# 示例4:使用標(biāo)志參數(shù)忽略大小寫
text4 = "Hello World, HELLO PYTHON"
result4 = re.findall(r'hello', text4, re.IGNORECASE)
print(f"示例4結(jié)果: {result4}") # 輸出: ['Hello', 'HELLO']
# 示例5:多行匹配模式
text5 = "Line 1\nLine 2\nLine 3"
result5 = re.findall(r'^Line \d', text5, re.MULTILINE)
print(f"示例5結(jié)果: {result5}") # 輸出: ['Line 1', 'Line 2', 'Line 3']
正則表達(dá)式中的 * 和 + 是貪婪的,會(huì)盡可能多地匹配字符
在量詞后加 ? 可以使其變?yōu)榉秦澙纺J剑M可能少地匹配字符
使用 ^ 和 $ 匹配字符串的開始和結(jié)束
使用 \b 匹配單詞邊界,避免部分匹配
正則表達(dá)式中的特殊字符(如 ., *, + 等)需要使用 \ 進(jìn)行轉(zhuǎn)義
可以使用原始字符串(在字符串前加 r)避免 Python 字符串轉(zhuǎn)義的干擾
不需要提取內(nèi)容時(shí),可以使用非捕獲組 (?:...) 提高效率
多個(gè)捕獲組的結(jié)果按元組形式返回,注意順序和數(shù)量
4.2.re.finditer("正則表達(dá)式","原字符串","可選參數(shù)"):主要作用是在字符串中查找所有非重疊的匹配項(xiàng),并返回一個(gè)包含匹配對(duì)象的迭代器。
re.finditer(pattern, string, flags=0) # 或(使用預(yù)編譯的正則對(duì)象) pattern_obj.finditer(string)
import re # 假設(shè)這是從網(wǎng)頁(yè)獲取的 HTML 片段(簡(jiǎn)化版) html = ''' <div class="item"> <span class="title">肖申克的救贖</span> </div> <div class="item"> <span class="title">霸王別姬</span> </div> ''' # 預(yù)編譯正則(匹配電影名稱) pattern = re.compile(r'<span class="title">(?P<name>.*?)</span>', re.S) # 使用 finditer() 查找所有匹配 matches = pattern.finditer(html) # 遍歷迭代器,提取每個(gè)匹配的信息 for match in matches: # 獲取整個(gè)匹配的文本(包含標(biāo)簽) print("完整匹配:", match.group(0)) # <span class="title">肖申克的救贖</span> # 獲取命名分組 'name' 的內(nèi)容(電影名稱) print("電影名稱:", match.group('name')) # 肖申克的救贖 # 獲取匹配的位置(在原始字符串中的索引) print("位置:", match.span()) # (例如 (19, 45),具體值取決于字符串) print("---")
4.3.re.sub("正則表達(dá)式","替換的字符串","原字符串","可選參數(shù)"):用于在字符串中替換所有匹配正則表達(dá)式的子串。這是處理文本數(shù)據(jù)時(shí)非常常用的功能,比如清洗數(shù)據(jù)、格式化文本等。
re.sub(pattern, repl, string, count=0, flags=0)
當(dāng) repl 是字符串時(shí),可以使用以下特殊語(yǔ)法:
\g<group>:引用指定編號(hào)或名稱的捕獲組\1,\2, ...:引用第 1、2 等捕獲組\g<0>:引用整個(gè)匹配的子串
import re
# 示例1:簡(jiǎn)單替換,將所有數(shù)字替換為X
text1 = "hello 123 world 456"
result1 = re.sub(r'\d', 'X', text1)
print(f"示例1結(jié)果: {result1}") # 輸出: hello XXX world XXX
# 示例2:使用捕獲組,交換姓名順序
text2 = "Zhang San, Li Si, Wang Wu"
result2 = re.sub(r'(\w+) (\w+)', r'\2 \1', text2)
print(f"示例2結(jié)果: {result2}") # 輸出: San Zhang, Si Li, Wu Wang
# 示例3:使用命名捕獲組,格式化日期
text3 = "2023-10-01"
result3 = re.sub(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})',
r'\g<month>/\g<day>/\g<year>', text3)
print(f"示例3結(jié)果: {result3}") # 輸出: 10/01/2023
# 示例4:使用函數(shù)進(jìn)行動(dòng)態(tài)替換,將數(shù)字乘以2
def double_number(match):
return str(int(match.group(0)) * 2)
text4 = "A1B2C3"
result4 = re.sub(r'\d', double_number, text4)
print(f"示例4結(jié)果: {result4}") # 輸出: A2B4C6
# 示例5:限制替換次數(shù)
text5 = "apple apple apple"
result5 = re.sub(r'apple', 'orange', text5, count=2)
print(f"示例5結(jié)果: {result5}") # 輸出: orange orange apple
# 示例6:忽略大小寫替換
text6 = "Hello World, hello Python"
result6 = re.sub(r'hello', 'hi', text6, flags=re.IGNORECASE)
print(f"示例6結(jié)果: {result6}") # 輸出: hi World, hi Python
def square_number(match):
num = int(match.group(0))
return str(num ** 2)
text = "a1b2c3"
result = re.sub(r'\d', square_number, text)
print(result) # 輸出: a1b4c9
- 數(shù)據(jù)清洗:移除或替換特殊字符、多余空格等
- 文本格式化:將日期、電話號(hào)碼等轉(zhuǎn)換為統(tǒng)一格式
- 敏感信息處理:替換或掩碼化敏感數(shù)據(jù)(如身份證號(hào)、信用卡號(hào))
- 語(yǔ)法轉(zhuǎn)換:在不同編程語(yǔ)言或格式之間轉(zhuǎn)換語(yǔ)法
- 模板替換:根據(jù)規(guī)則動(dòng)態(tài)生成文本內(nèi)容
正則表達(dá)式中的特殊字符需要使用 \ 進(jìn)行轉(zhuǎn)義
可以使用原始字符串(如 r'\d+')避免 Python 字符串轉(zhuǎn)義的干擾
使用 () 定義捕獲組,可以在替換字符串中引用
使用非捕獲組 (?:...) 避免不必要的捕獲,提高效率
替換字符串中的反斜杠需要轉(zhuǎn)義(如 \\ 表示一個(gè)反斜杠)
- 可以使用原始字符串簡(jiǎn)化處理(如
r'\\section')
re.finditer(pattern, string, flags=0)
result = re.finditer(r"\d+", "我今年42歲,我有2000000元")
for item in result:
print(item.group(0))
#輸出結(jié)果:42 2000000
import re
# 使用 re.finditer() 查找所有數(shù)字
result = re.finditer(r"\d+", "我今年42歲,我有2000000元")
# 遍歷迭代器并打印匹配結(jié)果
for match in result:
print(f"匹配到的數(shù)字: {match.group(0)}")
print(f"位置: {match.start()} - {match.end()}")
print(f"原始字符串中的片段: {match.string[match.start():match.end()]}")
print("-" * 20)
"""輸出結(jié)果:
匹配到的數(shù)字: 42
位置: 3 - 5
原始字符串中的片段: 42
--------------------
匹配到的數(shù)字: 2000000
位置: 8 - 15
原始字符串中的片段: 2000000
--------------------"""
group(0):返回整個(gè)匹配的字符串group(1), group(2), ...:返回第 1、2 等捕獲組的內(nèi)容start():返回匹配開始的位置end():返回匹配結(jié)束的位置span():返回一個(gè)元組(start, end)
import re # 示例1:查找第一個(gè)數(shù)字 text1 = "hello 123 world 456" match1 = re.search(r'\d+', text1) if match1: print(f"找到數(shù)字: {match1.group(0)}") # 輸出: 123 print(f"位置: {match1.start()} - {match1.end()}") # 輸出: 6 - 9 else: print("未找到匹配項(xiàng)") # 示例2:使用捕獲組提取信息 text2 = "我的郵箱是 example@domain.com,請(qǐng)查收" match2 = re.search(r'(\w+)@(\w+\.\w+)', text2) if match2: print(f"完整郵箱: {match2.group(0)}") # 輸出: example@domain.com print(f"用戶名: {match2.group(1)}") # 輸出: example print(f"域名: {match2.group(2)}") # 輸出: domain.com # 示例3:忽略大小寫查找 text3 = "Hello World" match3 = re.search(r'world', text3, re.IGNORECASE) if match3: print(f"找到匹配: {match3.group(0)}") # 輸出: World # 示例4:多行模式下的搜索 text4 = "第一行\(zhòng)n第二行\(zhòng)n第三行" match4 = re.search(r'^第(.*)行$', text4, re.MULTILINE) if match4: print(f"匹配行內(nèi)容: {match4.group(0)}") # 輸出: 第一行 print(f"捕獲內(nèi)容: {match4.group(1)}") # 輸出: 一
import re # 通過(guò)用戶輸入獲取密碼 password = input("請(qǐng)輸入密碼:") if re.search(r'^[a-zA-Z0-9]+$', password): print("密碼格式有效") else: print("密碼格式無(wú)效,只能包含字母和數(shù)字")
- 提取特定信息:
import re # 定義要搜索的文本 text = "這是一個(gè)測(cè)試,商品價(jià)格:99.99元" match = re.search(r'價(jià)格:(\d+\.\d+)元', text) if match: price = float(match.group(1)) print(f"商品價(jià)格: {price} 元") else: print("未找到價(jià)格信息") #輸出結(jié)果:商品價(jià)格: 99.99 元 #從用戶輸入獲取 text import re # 從用戶輸入獲取文本 text = input("請(qǐng)輸入包含價(jià)格的文本(例如:商品價(jià)格:99.99元):") # 修改正則表達(dá)式,允許匹配整數(shù)或小數(shù)價(jià)格 match = re.search(r'價(jià)格:(\d+(?:\.\d+)?)元', text) if match: try: price = float(match.group(1)) print(f"成功提取價(jià)格: {price} 元") except ValueError: print("錯(cuò)誤:無(wú)法將提取的內(nèi)容轉(zhuǎn)換為價(jià)格") else: print("未找到符合格式的價(jià)格信息") print("提示:請(qǐng)確保輸入的文本包含如'價(jià)格:99.99元'或'價(jià)格:100元'的格式") import re # 從文件讀取文本 try: with open('input.txt', 'r', encoding='utf-8') as file: text = file.read() except FileNotFoundError: print("文件未找到,請(qǐng)檢查文件路徑") exit() match = re.search(r'價(jià)格:(\d+\.\d+)元', text) if match: price = float(match.group(1)) print(f"商品價(jià)格: {price} 元") else: print("未找到價(jià)格信息")
- 驗(yàn)證輸入格式:
import re # 通過(guò)用戶輸入獲取電話號(hào)碼 phone_number = input("請(qǐng)輸入電話號(hào)碼:") if re.search(r'^\d{11}$', phone_number): print("手機(jī)號(hào)碼格式正確") else: print("手機(jī)號(hào)碼格式錯(cuò)誤,必須是11位數(shù)字"
4.6.re.match("正則表達(dá)式","原字符串","可選參數(shù)"):主要用于在字符串的起始位置對(duì)正則表達(dá)式進(jìn)行匹配。要是匹配成功,它會(huì)返回一個(gè)匹配對(duì)象;要是匹配失敗,則返回None。
re.match(pattern, string, flags=0)
group([group1, ...]):用于獲取一個(gè)或多個(gè)分組的匹配內(nèi)容。若不指定參數(shù),則返回整個(gè)匹配結(jié)果。groups():返回一個(gè)包含所有分組匹配結(jié)果的元組。start([group]):返回指定分組匹配的起始位置。若未指定分組,則返回整個(gè)匹配的起始位置。end([group]):返回指定分組匹配的結(jié)束位置(不包含該位置的字符)。span([group]):返回一個(gè)元組,包含指定分組匹配的起始和結(jié)束位置。
import re string = "Hello, world!" match = re.match("world", string) # 匹配失敗,返回None search = re.search("world", string) # 匹配成功,返回匹配對(duì)象 print(match) # 輸出:None print(search.group()) # 輸出:world
4.7.re.compile("正則表達(dá)式","可選參數(shù)"):用于將正則表達(dá)式模式編譯為一個(gè)正則表達(dá)式對(duì)象。編譯后的對(duì)象可以多次使用,叫做預(yù)加載,提高匹配效率,尤其在需要重復(fù)匹配相同模式的場(chǎng)景下性能更優(yōu)。
re.compile(pattern, flags=0)
import re # 編譯正則表達(dá)式 pattern = re.compile(r'\d+') # 匹配一個(gè)或多個(gè)數(shù)字 # 使用編譯后的對(duì)象進(jìn)行匹配 text = "Hello 123 World 456" # 查找所有匹配 matches = pattern.findall(text) print(f"所有匹配: {matches}") # 輸出: ['123', '456'] # 使用 search 方法查找第一個(gè)匹配 match = pattern.search(text) if match: print(f"第一個(gè)匹配: {match.group(0)}, 位置: {match.start()}") # 輸出: 第一個(gè)匹配: 123, 位置: 6
import re text = "Hello 123 World 456" matches = re.findall(r'\d+', text) # 每次調(diào)用都編譯一次正則表達(dá)式 print(matches)#輸出:['123','456']
import re pattern = re.compile(r'\d+') # 編譯一次 matches1 = pattern.findall("Hello 123") # 直接使用已編譯的對(duì)象 matches2 = pattern.findall("World 456") # 再次使用,無(wú)需重新編譯 print(matches1) # 輸出: ['123'] print(matches2) # 輸出: ['456']
pattern.match(string[, pos[, endpos]]):從字符串的起始位置開始匹配。pattern.search(string[, pos[, endpos]]):在字符串中搜索第一個(gè)匹配項(xiàng)。pattern.findall(string[, pos[, endpos]]):返回所有匹配的字符串列表。pattern.finditer(string[, pos[, endpos]]):返回匹配對(duì)象的迭代器。pattern.sub(repl, string[, count]):替換匹配的子串。
import re # 預(yù)編譯正則表達(dá)式 email_pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b') # 待驗(yàn)證的郵箱列表 emails = ["test@example.com", "invalid.email", "user.name+tag@domain.co.uk"] # 循環(huán)驗(yàn)證郵箱 for email in emails: if email_pattern.match(email): print(f"{email} 是有效的郵箱地址") else: print(f"{email} 不是有效的郵箱地址")
re.IGNORECASE或re.I:忽略大小寫。re.MULTILINE或re.M:多行匹配模式。re.DOTALL或re.S:使.匹配包括換行符在內(nèi)的所有字符。
import re # 添加模塊導(dǎo)入語(yǔ)句 pattern = re.compile(r'hello', re.IGNORECASE) # 忽略大小寫的匹配 print(pattern.search("Hello World").group(0)) # 輸出: Hello
總之,re.compile 是優(yōu)化正則表達(dá)式性能的重要工具,尤其適用于需要重復(fù)使用同一模式的場(chǎng)景。
4.8.re.S: 匹配模式修飾符,也可以寫作 re.DOTALL。
import re text = "hello\nworld" # 不使用 re.S,無(wú)法匹配換行符 print(re.findall("hello.world", text)) # 輸出: [] # 使用 re.S,點(diǎn)號(hào)可以匹配換行符 print(re.findall("hello.world", text, re.S)) # 輸出: ['hello\nworld']
這個(gè)修飾符在需要匹配多行文本時(shí)非常有用,比如處理包含換行的字符串或多行文本內(nèi)容。re.DOTALL 是更具描述性的別名,功能與 re.S 完全相同。
re正則表達(dá)式代碼示例:
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)</span>', re.S)
代碼解釋:
5.CSV文件寫入(內(nèi)置模塊)
import csv # 數(shù)據(jù) data = [ ["姓名", "年齡", "城市"], ["張三", 25, "北京"], ["李四", 30, "上海"], ["王五", 28, "廣州"] ] # 寫入CSV文件 with open("people.csv", "w", newline="", encoding="utf-8") as file: writer = csv.writer(file) # 寫入多行 writer.writerows(data) # 也可以單行寫入 # writer.writerow(["趙六", 35, "深圳"])
import csv # 數(shù)據(jù) data = [ {"姓名": "張三", "年齡": 25, "城市": "北京"}, {"姓名": "李四", "年齡": 30, "城市": "上海"}, {"姓名": "王五", "年齡": 28, "城市": "廣州"} ] # 字段名(表頭) fieldnames = ["姓名", "年齡", "城市"] with open("people_dict.csv", "w", newline="", encoding="utf-8") as file: writer = csv.DictWriter(file, fieldnames=fieldnames) # 寫入表頭 writer.writeheader() # 寫入數(shù)據(jù) writer.writerows(data) # 單行寫入 # writer.writerow({"姓名": "趙六", "年齡": 35, "城市": "深圳"})
import csv with open("custom_sep.csv", "w", newline="", encoding="utf-8") as file: # 使用制表符作為分隔符(類似TSV文件) writer = csv.writer(file, delimiter="\t") writer.writerows([["a", "b", "c"], ["1", "2", "3"]])
注意事項(xiàng):
5.4.enumerate(迭代對(duì)象,[0]:):枚舉對(duì)象轉(zhuǎn)換:用于將一個(gè)可迭代對(duì)象(如列表、元組、字符串等)轉(zhuǎn)換為一個(gè)枚舉對(duì)象,在遍歷過(guò)程中同時(shí)返回「元素的索引」和「元素的值」。
enumerate(iterable, start=0)
當(dāng)你需要遍歷一個(gè)序列,同時(shí)又需要知道每個(gè)元素在序列中的位置(索引)時(shí),enumerate() 可以簡(jiǎn)化代碼。
例如,不使用 enumerate() 時(shí),可能需要這樣寫:
fruits = ['apple', 'banana', 'cherry'] index = 0 for fruit in fruits: print(f"Index: {index}, Fruit: {fruit}") index += 1 # 手動(dòng)維護(hù)索引
而使用 enumerate() 后,代碼更簡(jiǎn)潔:
fruits = ['apple', 'banana', 'cherry'] for index, fruit in enumerate(fruits): print(f"Index: {index}, Fruit: {fruit}") ''' 輸出結(jié)果: Index: 1, Fruit: apple Index: 2, Fruit: banana Index: 3, Fruit: cherry '''
如果從第二個(gè)數(shù)據(jù)(banana)開始迭代,可以先對(duì)列表進(jìn)行切片處理,從索引 1 開始(因?yàn)?Python 列表索引從 0 開始,第二個(gè)元素的索引是 1),再傳入enumerate()函數(shù)中。
fruits = ['apple', 'banana', 'cherry'] # 從索引1開始切片,只處理'banana'和'cherry' for index, fruit in enumerate(fruits[1:]): # 注意:此時(shí)的index是相對(duì)于切片后列表的索引(從0開始) # 如果需要顯示原列表中的真實(shí)索引,需要加上偏移量1 print(f"原索引: {index + 1}, Fruit: {fruit}") ''' 輸出結(jié)果: 原索引: 1, Fruit: banana 原索引: 2, Fruit: cherry '''
簡(jiǎn)單說(shuō),enumerate() 的核心作用就是在遍歷過(guò)程中同時(shí)獲取元素及其位置信息,讓代碼更簡(jiǎn)潔高效。
自動(dòng)爬蟲
1.selemium:是一套用于Web應(yīng)用程序自動(dòng)化測(cè)試的工具集,同時(shí)也廣泛用于網(wǎng)絡(luò)數(shù)據(jù)爬取(合規(guī)場(chǎng)景下)、自動(dòng)化操作瀏覽器(如自動(dòng)填寫表單、模擬用戶交互等)。它的核心能力是直接控制瀏覽器(如 Chrome、Firefox),模擬真實(shí)用戶的操作行為(點(diǎn)擊、輸入、跳轉(zhuǎn)等),是 Web 自動(dòng)化領(lǐng)域最流行的工具之一。
- 開發(fā)者編寫代碼:通過(guò) Python/Java 等語(yǔ)言調(diào)用 Selenium WebDriver 的 API(如
click()、send_keys())。 - WebDriver 轉(zhuǎn)發(fā)指令:WebDriver 將代碼中的操作指令(如 “點(diǎn)擊按鈕”)轉(zhuǎn)換為瀏覽器能識(shí)別的協(xié)議(如 W3C WebDriver 協(xié)議)。
- 瀏覽器驅(qū)動(dòng)執(zhí)行:需提前安裝對(duì)應(yīng)瀏覽器的 “驅(qū)動(dòng)程序”(如 Chrome 對(duì)應(yīng)
chromedriver),驅(qū)動(dòng)接收指令后,控制瀏覽器執(zhí)行具體操作。 - 瀏覽器返回結(jié)果:操作結(jié)果(如頁(yè)面渲染、元素狀態(tài)變化)通過(guò)驅(qū)動(dòng)反饋給 WebDriver,最終可在代碼中獲取(如獲取頁(yè)面源碼、元素文本)。





浙公網(wǎng)安備 33010602011771號(hào)