程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python之Urllib使用

編輯:Python

1. 什麼是互聯網爬蟲?

如果我們把互聯網比作一張大的蜘蛛網,那一台計算機上的數據便是蜘蛛網上的一個獵物,而爬蟲程序就是一只小

蜘蛛,沿著蜘蛛網抓取自己想要的數據

解釋1:通過一個程序,根據Url(http://www.taobao.com)進行爬取網頁,獲取有用信息
解釋2:使用程序模擬浏覽器,去向服務器發送請求,獲取響應信息

2. 爬蟲核心?

  1. 爬取網頁:爬取整個網頁 包含了網頁中所有得內容

  2. 解析數據:將網頁中你得到的數據 進行解析

  3. 難點:爬蟲和反爬蟲之間的博弈

3. 爬蟲的用途?

  • 數據分析/人工數據集

  • 社交軟件冷啟動

  • 輿情監控

  • 競爭對手監控

4. 爬蟲分類?

通用爬蟲:
實例
百度、360、google、sougou等搜索引擎‐‐‐伯樂在線
功能
訪問網頁‐>抓取數據‐>數據存儲‐>數據處理‐>提供檢索服務
robots協議
一個約定俗成的協議,添加robots.txt文件,來說明本網站哪些內容不可以被抓取,起不到限制作用 自己寫的 爬蟲無需遵守
網站排名(SEO)
1. 根據pagerank算法值進行排名(參考個網站流量、點擊率等指標)
2. 百度競價排名
缺點
1. 抓取的數據大多是無用的
2.不能根據用戶的需求來精准獲取數據
聚焦爬蟲
功能
根據需求,實現爬蟲程序,抓取需要的數據
設計思路
1.確定要爬取的url
如何獲取Url
2.模擬浏覽器通過http協議訪問url,獲取服務器返回的html代碼
如何訪問
3.解析html字符串(根據一定規則提取需要的數據)
如何解析

5. 反爬手段

  1. User‐Agent:

    • User Agent中文名為用戶代理,簡稱 UA,它是一個特殊字符串頭,使得服務器能夠識別客戶使用的操作系統及版 本、CPU 類型、浏覽器及版本、浏覽器渲染引擎、浏覽器語言、浏覽器插件等。
  2. 代理IP:

    • 西次代理
    • 快代理
    • 什麼是高匿名、匿名和透明代理?它們有什麼區別?
      • 使用透明代理,對方服務器可以知道你使用了代理,並且也知道你的真實IP。
      • 使用匿名代理,對方服務器可以知道你使用了代理,但不知道你的真實IP。
      • 使用高匿名代理,對方服務器不知道你使用了代理,更不知道你的真實IP。
  3. 驗證碼訪問

    • 打碼平台

      • 雲打碼平台

      • 超級

  4. 動態加載網頁 網站返回的是js數據 並不是網頁的真實數據

    • selenium驅動真實的浏覽器發送請求
  5. 數據加密

    • 分析js代碼

6. urllib庫使用

urllib.request.urlopen()模擬浏覽器向服務器發送請求

response 服務器返回的數據

  • response的數據類型是HttpResponse

  • 字節‐‐>字符串 解碼decode

  • 字符串‐‐>字節 編碼encode

  • read() 字節形式讀取二進制 擴展:rede(5)返回前幾個字節

  • readline() 讀取一行

  • readlines() 一行一行讀取 直至結束

  • getcode() 獲取狀態碼

  • geturl() 獲取url

  • getheaders() 獲取headers

  • urllib.request.urlretrieve()

    • 請求網頁
    • 請求圖片
    • 請求視頻

基本使用:

爬取百度首頁源碼:

# 使用urllib獲取百度首頁的源碼
import urllib.request
# 定義一個url
url = 'http://www.baidu.com'
# 模擬浏覽器向服務器發送請求
response = urllib.request.urlopen(url)
# 獲取響應中的頁面源碼
# read方法,返回的是字節形式的二進制數據
# 將二進制數據轉換為字符串
# 二進制 =》字符串 解碼 decode('編碼格式'),編碼格式在頁面的head標簽meta的charset屬性
content = response.read().decode('utf-8')
print(content)

一個類型和六個方法:

import urllib.request
url = 'http://www.baidu.com'
response = urllib.request.urlopen(url)
# response 是HTTPResponse類型
# print(type(response))
# 按照一個字節一個字節的去讀
# content = response.read()
# 讀取一行
# content = response.readline()
# content = response.readlines()
# 返回狀態碼,如果是200,就證明證明沒有錯
# print(response.getcode())
# 返回訪問的url地址
# print(response.geturl())
# 獲取的是一些狀態信息
print(response.getheaders())

下載:

import urllib.request
# 下載一個網頁
# url_page = 'http://www.baidu.com'
# urllib.request.urlretrieve(url_page, 'baidu.html')
# 下載圖片
# url_img = 'https://img-home.csdnimg.cn/images/20201124032511.png'
# urllib.request.urlretrieve(url=url_img, filename='csdn.jpg')
# 下載視頻
url_video = 'https://vd2.bdstatic.com/mda-jmsy151cd1ijyz3r/hd/mda-jmsy151cd1ijyz3r.mp4?v_from_s=hkapp-haokan-hnb&auth_key=1656516999-0-0-1fcd521c8a93ff8141ca1645aa7c315c&bcevod_channel=searchbox_feed&pd=1&cd=0&pt=3&logid=0398986023&vid=3985750168738470460&abtest=102784_2-102836_3-102982_3-3000232_2&klogid=0398986023'
urllib.request.urlretrieve(url_video, 'test.mp4')

7. 請求對象的定制

UA介紹:User Agent中文名為用戶代理,簡稱 UA,它是一個特殊字符串頭,使得服務器能夠識別客戶使用的操作系統及版本、CPU 類型、浏覽器及版本。浏覽器內核、浏覽器渲染引擎、浏覽器語言、浏覽器插件等

語法:request = urllib.request.Request()

示例:

import urllib.request
url = 'https://www.baidu.com'
# headers詳情見下邊圖片
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)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)

編碼的由來:

由於計算機是美國人發明的,因此,最早只有127個字符被編碼到計算機裡,也就是大小寫英文字母、數字和一些符號, 這個編碼表被稱為ASCII編碼,比如大寫字母A的編碼是65,小寫字母z的編碼是122。 但是要處理中文顯然一個字節是不夠的,至少需要兩個字節,而且還不能和ASCII編碼沖突, 所以,中國制定了GB2312編碼,用來把中文編進去。 你可以想得到的是,全世界有上百種語言,日本把日文編到Shift_JIS裡,韓國把韓文編到Euc‐kr裡, 各國有各國的標准,就會不可避免地出現沖突,結果就是,在多語言混合的文本中,顯示出來會有亂碼。 因此,Unicode應運而生。Unicode把所有語言都統一到一套編碼裡,這樣就不會再有亂碼問題了。 Unicode標准也在不斷發展,但最常用的是用兩個字節表示一個字符(如果要用到非常偏僻的字符,就需要4個字節)。 現代操作系統和大多數編程語言都直接支持Unicode。

8. 編解碼

1.get請求方式:urllib.parse.quote()

import urllib.request
import urllib.parse
url = 'https://www.baidu.com/s?wd='
# 把參數轉為ASCII編碼
url += url + urllib.parse.quote('周傑倫')
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)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)

2. get請求方式:urllib.parse.urlencode()

import urllib.request
import urllib.parse
url = 'https://www.baidu.com/s?'
# 利用字典類型編碼傳參
data = {

'wd': '蔡依林',
'sex': '女'
}
url += urllib.parse.urlencode(data)
print(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=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)

3.post請求方式

import urllib.request
import urllib.parse
import json
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': 'hello'
}
# post請求的參數必須要進行編碼
data = urllib.parse.urlencode(data).encode('utf-8')
# post請求的參數要放在請求對象定制的參數中
request = urllib.request.Request(url=url, data=data, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
# 字符串轉為json對象
obj = json.loads(content)
print(obj)

post和get區別:

  1. get請求方式的參數必須編碼,參數是拼接到url後面,編碼之後不需要調用encode方法

  2. post請求方式的參數必須編碼,參數是放在請求對象定制的方法中,編碼之後需要調用encode方法

import urllib.request
import urllib.parse
import json
url = 'https://fanyi.baidu.com/v2transapi?from=en&to=zh'
# 浏覽器控制台查看header
headers = {

'Cookie': 'BIDUPSID=3223FE11042DAD864DA852D876FDDFA9; PSTM=1654091563; BAIDUID=3223FE11042DAD86DD7C657D63E1E52C:FG=1; APPGUIDE_10_0_2=1; SOUND_PREFER_SWITCH=1; REALTIME_TRANS_SWITCH=1; HISTORY_SWITCH=1; FANYI_WORD_SWITCH=1; SOUND_SPD_SWITCH=1; BDUSS=HExR09IbHgtdi1ibEtmblo2MVdRdHdyelc5UGk3Q1MyYk1mWUZJQW9pWEtCYjlpRVFBQUFBJCQAAAAAAAAAAAEAAAABrg80x-O-~dK7ysDI4cfp2LwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMp4l2LKeJdiM; BDUSS_BFESS=HExR09IbHgtdi1ibEtmblo2MVdRdHdyelc5UGk3Q1MyYk1mWUZJQW9pWEtCYjlpRVFBQUFBJCQAAAAAAAAAAAEAAAABrg80x-O-~dK7ysDI4cfp2LwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMp4l2LKeJdiM; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; PSINO=1; H_PS_PSSID=36545_36722_36454_31253_36663_36413_36691_36167_36693_36698_36075_36744_26350_36685_36469; BA_HECTOR=2081850k2l24ag24011hbrb0l14; ZFY=eQSkt9DtBzoEZ2DdNJW5f:BgPs:BesKMBKOGsMVfN7H5c:C; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1654092726,1656597526; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1656597526; ab_sr=1.0.1_ZjlmNzdiNWNjYTIwYTY4NTcxNGY3NDk3NjE1NGY3YmZlNTdjMjdiMzhkYjJiZWE3ZjcyOGI0NGMwNjZkYWU1YzgyMmQzMjU0ZjQ2NjBhMzI0ZTVlMDk2MjZiMjAzMDE5ZjQ2NTA0ODNlYWQ2NjEzMTk5ZWRhMmZkZTE2NWJmZDc1MDkyNDQxNTUwMzk1YjczOTdiNDUxYTJkMjlkZDA1ZmM1MzVkNWIzYjJkYWQ2Y2Q5ZmNiODk5MWZkNzBkYjUz'
}
data = {

'from': 'en',
'to': 'zh',
'query': 'hello',
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '54706.276099',
'token': '406f9ef9798def66b41a2d8f61f5c96a',
'domain': 'common'
}
data = urllib.parse.urlencode(data).encode('utf-8')
request = urllib.request.Request(url=url, data=data, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
obj = json.loads(content)
print(obj)
# python對象轉換為json字符串 ensure_ascii=False 忽略字符集編碼
s = json.dumps(obj,ensure_ascii=False)
print(s)

9. ajax的get請求

簡單示例:

import urllib.request
url = 'https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&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'
}
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
# 將內容保存在文件中
# open默認使用gbk編碼,如果想保存漢字,指定編碼格式為utf-8
# fp = open('douban.json', 'w', encoding='utf-8')
# fp.write(content)
# fp.close()
# 另一種寫法
with open('douban1.json','w', encoding='utf-8') as fp:
fp.write(content)

獲取豆瓣的第一頁至指定頁數的數據

import urllib.request
import urllib.parse
# 創建定制請求
def create_request(page):
url = 'https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&'
# 計算當前頁數據的起始和終止條數
start = (page - 1) * 20
limit = 20
data = {

'start': start,
'limit': limit
}
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'
}
url += urllib.parse.urlencode(data)
request = urllib.request.Request(url=url, headers=headers)
return request
# 獲取請求內容
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
# 將每個內容寫入到文件中
def down_load(content, page):
with open('douban_' + str(page) + '.json', 'w', encoding='utf-8') as fp:
fp.write(content)
fp.close()
# 程序的入口,寫不寫都可以
if __name__ == '__main__':
start_page = 1
end_page = int(input("請輸入頁數:"))
for i in range(start_page, end_page + 1):
request = create_request(i)
content = get_content(request)
down_load(content, i)

10. ajax的post請求

爬取KFC門店信息(按分頁)

import urllib.request
import urllib.parse
# 定制請求
def create_request(page):
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
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 = {

'cname': '北京',
'pid': '',
'pageIndex': page,
'pageSize': 10,
}
data = urllib.parse.urlencode(data).encode('utf-8')
request = urllib.request.Request(url=url, headers=headers, data=data)
return request
# 獲取請求內容
def get_content(request):
response = urllib.request.urlopen(request)
return response.read().decode('utf-8')
# 將內容寫入到本地文件
def down_load(page, content):
with open('KFC_' + str(page) + '.json', 'w', encoding='utf-8') as f:
f.write(content)
f.close()
if __name__ == '__main__':
start_page = 1
end_page = int(input('請輸入頁數:'))
for i in range(start_page, end_page + 1):
request = create_request(i)
content = get_content(request)
down_load(i, content)

11. URLError\HTTPError

簡介:

  1. HTTPError類是URLError類的子類

  2. 導入的包urllib.error.HTTPError urllib.error.URLError

  3. http錯誤:http錯誤是針對浏覽器無法連接到服務器而增加出來的錯誤提示。引導並告訴浏覽者該頁是哪裡出了問題。

  4. 通過urllib發送請求的時候,有可能會發送失敗,這個時候如果想讓你的代碼更加的健壯,可以通過try‐

except進行捕獲異常,異常有兩類,URLError\HTTPError

import urllib.request
import urllib.error
url = 'https://blog.csdn.net/weixin_43847283/article/details/1255564151'
# url = "http://adad121a.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'
}
try:
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
print(response)
content = response.read().decode('utf-8')
except urllib.error.HTTPError:
print("地址錯誤")
except urllib.error.URLError:
print("地址錯誤")

12. cookie登錄

有些網站會把cookie放入header去請求,cookie存放的是登錄之後的信息。請求的時候必須帶上cookie才可以請求

13.Handler處理器

  • urllib.request.urlopen(url)

    • 不能定制請求頭
  • urllib.request.Request(url,headers,data)

    • 可以定制請求頭
  • Handler

    • 定制更高級的請求頭(隨著業務邏輯的復雜 請求對象的定制已經滿足不了我們的需求(動態cookie和代理不能使用請求對象的定制)
import urllib.request
url = '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)
# 獲取headler對象
handler = urllib.request.HTTPHandler()
# 獲取opener對象
opener = urllib.request.build_opener(handler)
#調用open方法
response = opener.open(request)
print(response.read().decode('utf‐8'))

14. 代理服務器

  1. 代理的常用功能?

    • 突破自身IP訪問限制,訪問國外站點。

    • 訪問一些單位或團體內部資源

      • 擴展:某大學FTP(前提是該代理地址在該資源的允許訪問范圍之內),使用教育網內地址段免費代理服務器,就可以用於對教育網開放的各類FTP下載上傳,以及各類資料查詢共享等服務。
    • 提高訪問速度

      • 擴展:通常代理服務器都設置一個較大的硬盤緩沖區,當有外界的信息通過時,同時也將其保存到緩沖區中,當其他用戶再訪問相同的信息時, 則直接由緩沖區中取出信息,傳給用戶,以提高訪問速度。
    • 隱藏真實IP

      • 擴展:上網者也可以通過這種方法隱藏自己的IP,免受攻擊。

2.代碼配置代理

  • 創建Reuqest對象

  • 創建ProxyHandler對象

  • handler對象創建opener對象

  • 使用opener.open函數發送請求

import urllib.request
import random
url = 'http://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)
# 定義一個代理池
proxies = [{
"http": "127.0.0.1:1"}, {
"http": "127.0.0.1:2"}]
# 隨機取出一個代理ip
proxie = random.choice(proxies)
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)
content = response.read().decode('utf‐8')
print(content)
with open('dl.html', 'w', encoding='utf‐8')as fp:
fp.write(content)

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved