如果我們把互聯網比作一張大的蜘蛛網,那一台計算機上的數據便是蜘蛛網上的一個獵物,而爬蟲程序就是一只小
蜘蛛,沿著蜘蛛網抓取自己想要的數據
解釋1:通過一個程序,根據Url(http://www.taobao.com)進行爬取網頁,獲取有用信息
解釋2:使用程序模擬浏覽器,去向服務器發送請求,獲取響應信息
爬取網頁:爬取整個網頁 包含了網頁中所有得內容
解析數據:將網頁中你得到的數據 進行解析
難點:爬蟲和反爬蟲之間的博弈
數據分析/人工數據集
社交軟件冷啟動
輿情監控
競爭對手監控
通用爬蟲:
實例
百度、360、google、sougou等搜索引擎‐‐‐伯樂在線
功能
訪問網頁‐>抓取數據‐>數據存儲‐>數據處理‐>提供檢索服務
robots協議
一個約定俗成的協議,添加robots.txt文件,來說明本網站哪些內容不可以被抓取,起不到限制作用 自己寫的 爬蟲無需遵守
網站排名(SEO)
1. 根據pagerank算法值進行排名(參考個網站流量、點擊率等指標)
2. 百度競價排名
缺點
1. 抓取的數據大多是無用的
2.不能根據用戶的需求來精准獲取數據
聚焦爬蟲
功能
根據需求,實現爬蟲程序,抓取需要的數據
設計思路
1.確定要爬取的url
如何獲取Url
2.模擬浏覽器通過http協議訪問url,獲取服務器返回的html代碼
如何訪問
3.解析html字符串(根據一定規則提取需要的數據)
如何解析
User‐Agent:
代理IP:
驗證碼訪問
打碼平台
雲打碼平台
超級
動態加載網頁 網站返回的是js數據 並不是網頁的真實數據
數據加密
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')
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。
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)
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)
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區別:
get請求方式的參數必須編碼,參數是拼接到url後面,編碼之後不需要調用encode方法
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)
簡單示例:
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)
爬取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)
簡介:
HTTPError
類是URLError
類的子類
導入的包urllib.error.HTTPError urllib.error.URLError
http
錯誤:http
錯誤是針對浏覽器無法連接到服務器而增加出來的錯誤提示。引導並告訴浏覽者該頁是哪裡出了問題。
通過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("地址錯誤")
有些網站會把cookie
放入header
去請求,cookie
存放的是登錄之後的信息。請求的時候必須帶上cookie
才可以請求
urllib.request.urlopen(url)
urllib.request.Request(url,headers,data)
Handler
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'))
代理的常用功能?
突破自身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)