一 基本流程:

#1、發起請求
使用http庫向目標站點發起請求,即發送一個Request
Request包含:請求頭、請求體等
#2、獲取響應內容
如果服務器能正常響應,則會得到一個Response
Response包含:html,json,圖片,視頻等
#3、解析內容
解析html數據:正則表達式,第三方解析庫如Beautifulsoup,pyquery等
解析json數據:json模塊
解析二進制數據:以b的方式寫入文件
#4、保存數據
數據庫
文件
二 請求與響應

#http協議:http://www.cnblogs.com/linhaifeng/articles/8243379.html
#Request:用戶將自己的信息通過瀏覽器(socket client)發送給服務器(socket server)
#Response:服務器接收請求,分析用戶發來的請求信息,然后返回數據(返回的數據中可能包含其他鏈接,如:圖片,js,css等)
#ps:瀏覽器在接收Response后,會解析其內容來顯示給用戶,而爬蟲程序在模擬瀏覽器發送請求然后接收Response后,是要提取其中的有用數據。
三 Request
#1、請求方式:
常用的請求方式:GET,POST
其他請求方式:HEAD,PUT,DELETE,OPTHONS
ps:用瀏覽器演示get與post的區別,(用登錄演示post)
post與get請求最終都會拼接成這種形式:k1=xxx&k2=yyy&k3=zzz
post請求的參數放在請求體內:
可用瀏覽器查看,存放於form data內
get請求的參數直接放在url后
#2、請求url
url全稱統一資源定位符,如一個網頁文檔,一張圖片
一個視頻等都可以用url唯一來確定
url編碼
https://www.baidu.com/s?wd=圖片
圖片會被編碼(看示例代碼)
網頁的加載過程是:
加載一個網頁,通常都是先加載document文檔,
在解析document文檔的時候,遇到鏈接,則針對超鏈接發起下載圖片的請求
#3、請求頭
User-agent:請求頭中如果沒有user-agent客戶端配置,
服務端可能將你當做一個非法用戶
host
cookies:cookie用來保存登錄信息
一般做爬蟲都會加上請求頭
#4、請求體
如果是get方式,請求體沒有內容
如果是post方式,請求體是format data
ps:
1、登錄窗口,文件上傳等,信息都會被附加到請求體內
2、登錄,輸入錯誤的用戶名密碼,然后提交,就可以看到post,正確登錄后頁面通常會跳轉,無法捕捉到post
# urlencode是將在請求出現的查找關鍵字信息轉為urlencode編碼
from urllib.parse import urlencode
import requests
headers={
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Cookie':'H_WISE_SIDS=101556_115474_115442_114743_108373_100099_115725_106201_107320_115339_114797_115553_116093_115546_115625_115446_114329_115350_114275_116040_110085; PSTM=1494300712; BAIDUID=42FE2934E37AF7AD1FA31D8CC7006D45:FG=1; BIDUPSID=2996557DB2710279BD865C50F9A68615; MCITY=-%3A; __cfduid=da9f97dea6458ca26aa4278280752ebb01508939712; BDSFRCVID=PGLsJeCCxG3wt_3ZUrBLDfv2D_qBZSjAgcEe3J; H_BDCLCKID_SF=tJAOoCLytI03qn5zq4Oh-4oHhxoJq5QxbT7Z0l8KtfcNVJQs-lCMhbtp-l3GJPoLWK6hBKQmWIQHDnbsbq0M2tcQXR5-WROCte74KKJx-4PWeIJo5tKh04JbhUJiB5OLBan7Lq7xfDDbbDtmej_3-PC3ql6354Rj2C_X3b7EfKjIOtO_bfbT2MbyeqrNQlTkLIvXoITJQD_bEP3Fbfj2DPQ3KabZqjDjJbue_I05f-oqebT4btbMqRtthf5KeJ3KaKrKW5rJabC3hPJeKU6qLT5Xjh6B5qDfyDoAbKOt-IOjhb5hMpnx-p0njxQyaR3RL2Kj0p_EWpcxsCQqLUonDh8L3H7MJUntKjnRonTO5hvvhb6O3M7-XpOhDG0fJjtJJbksQJ5e24oqHP-kKPrV-4oH5MQy5toyHD7yWCvjWlT5OR5Jj6KMjMkb3xbz2fcpMIrjob8M5CQESInv3MA--fcLD2ch5-3eQgTI3fbIJJjWsq0x0-jle-bQypoa-U0j2COMahkMal7xO-QO05CaD53yDNDqtjn-5TIX_CjJbnA_Hn7zepoxebtpbt-qJJjzMerW_Mc8QUJBH4tR-T3keh-83xbnBT5KaKO2-RnPXbcWjt_lWh_bLf_kQN3TbxuO5bRiL66I0h6jDn3oyT3VXp0n54nTqjDHfRuDVItXf-L_qtDk-PnVeUP3DhbZKxtqtDKjXJ7X2fclHJ7z-R3IBPCD0tjk-6JnWncKaRcI3poiqKtmjJb6XJkl2HQ405OT-6-O0KJcbRodobAwhPJvyT8DXnO7-fRTfJuJ_DDMJDD3fP36q4QV-JIehmT22jnT32JeaJ5n0-nnhP3mBTbA3JDYX-Oh-jjRX56GhfO_0R3jsJKRy66jK4JKjHKet6vP; ispeed_lsm=0; H_PS_PSSID=1421_24558_21120_17001_24880_22072; BD_UPN=123253; H_PS_645EC=44be6I1wqYYVvyugm2gc3PK9PoSa26pxhzOVbeQrn2rRadHvKoI%2BCbN5K%2Bg; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598',
'Host':'www.baidu.com',
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
# response=requests.get('https://www.baidu.com/s?'+urlencode({'wd':'美女'}),headers=headers)
response=requests.get('https://www.baidu.com/s',params={'wd':'美女'},headers=headers) #params內部就是調用urlencode
print(response.text)
四 Response
#1、響應狀態
200:代表成功
301:代表跳轉
404:文件不存在
403:權限
502:服務器錯誤
#2、Respone header
set-cookie:可能有多個,是來告訴瀏覽器,把cookie保存下來
#3、preview就是網頁源代碼
最主要的部分,包含了請求資源的內容
如網頁html,圖片
二進制數據等
五 總結及爬取梨視屏網站
#1、總結爬蟲流程:
爬取--->解析--->存儲
#2、爬蟲所需工具:
請求庫:requests,selenium
解析庫:正則,beautifulsoup,pyquery
存儲庫:文件,MySQL,Mongodb,Redis
#3、爬蟲常用框架:
scrapy
# 1.爬取首頁數據,解析獲取視頻的詳情鏈接
# 2.遍歷每一個詳情鏈接,並訪問
# 3.從詳情頁面解析得到需要的數據 (視頻鏈接,標題,詳情,時間,收藏次數)
import requests
import re
import os
from threading import Thread
from concurrent.futures import ThreadPoolExecutor
base_url = "https://www.pearvideo.com/"
def get_index():
res = requests.get(base_url,headers={
"user-agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
"referer": "https: // www.baidu.com / link?url = fUq54ztdrrLaIUXa - p6B9tuWXC3byFJCyBKuvuJ_qsPw8QLrWIfekFKGgmhqITyF & wd = & eqid = c5366da10000199a000000025c45768a"
})
return res.text
def parser_index(text):
urls = re.findall('<a href="(.*?)" class="vervideo-lilink actplay">',text)
urls = [base_url + i for i in urls]
# print(urls)
return urls
def get_details(url):
res = requests.get(url)
print(res.status_code)
return res.text
def parser_details(text):
# 視頻的地址
video_url = re.search(r'srcUrl="(.*?\.mp4)"',text).group(1)
# 標題
title = re.search('<h1 class="video-tt">(.*?)</h1>',text).group(1)
# 詳情
content = re.search('<div class="summary">(.*?)</div>',text).group(1)
# 時間
date = re.search('<div class="date">(.*?)</div>', text).group(1)
# 點贊數量
count = re.search('<div class="fav" data-id=".*?">(.*?)</div>', text).group(1)
return {"video_url":video_url,"title":title,"content":content,"date":date,"count":count}
def download_video(url,title):
data = requests.get(url)
if not os.path.exists("videos"):
os.makedirs("videos")
filename = os.path.join("videos",title)+".mp4"
filename = filename.replace(":","_")
with open(filename,"wb") as f:
f.write(data.content)
print("%s download finished!" % title)
if __name__ == '__main__':
pool = ThreadPoolExecutor(5)
data = get_index()
urls = parser_index(data)
for i in urls:
t = get_details(i)
dic = parser_details(t)
# Thread(target=download_video,args=(dic["video_url"],dic["title"])).start()
pool.submit(download_video,dic["video_url"],dic["title"])
print("submit task",dic["title"])
print("submit finished")