一 爬蟲是什么
#1、什么是互聯網? 互聯網是由網絡設備(網線,路由器,交換機,防火牆等等)和一台台計算機連接而成,像一張網一樣。 #2、互聯網建立的目的? 互聯網的核心價值在於數據的共享/傳遞:數據是存放於一台台計算機上的,而將計算機互聯到一起的目的就是為了能夠方便彼此之間的數據共享/傳遞,否則你只能拿U盤去別人的計算機上拷貝數據了。 #3、什么是上網?爬蟲要做的是什么? 我們所謂的上網便是由用戶端計算機發送請求給目標計算機,將目標計算機的數據下載到本地的過程。 #3.1 只不過,用戶獲取網絡數據的方式是: 瀏覽器提交請求->下載網頁代碼->解析/渲染成頁面。 ``` #3.2 而爬蟲程序要做的就是: 模擬瀏覽器發送請求->下載網頁代碼->只提取有用的數據->存放於數據庫或文件中 #3.1與3.2的區別在於: ``` 我們的爬蟲程序只提取網頁代碼中對我們有用的數據 #4、總結爬蟲 #4.1 爬蟲的比喻: 如果我們把互聯網比作一張大的蜘蛛網,那一台計算機上的數據便是蜘蛛網上的一個獵物,而爬蟲程序就是一只小蜘蛛,沿着蜘蛛網抓取自己想要的獵物/數據 ``` #4.2 爬蟲的定義: ``` 向網站發起請求,獲取資源后分析並提取有用數據的程序 ``` #4.3 爬蟲的價值: 互聯網中最有價值的便是數據,比如天貓商城的商品信息,鏈家網的租房信息,雪球網的證券投資信息等等,這些數據都代表了各個行業的真金白銀,可以說,誰掌握了行業內的第一手數據,誰就成了整個行業的主宰,如果把整個互聯網的數據比喻為一座寶藏,那我們的爬蟲課程就是來教大家如何來高效地挖掘這些寶藏,掌握了爬蟲技能,你就成了所有互聯網信息公司幕后的老板,換言之,它們都在免費為你提供有價值的數據。```
二 爬蟲的基本流程
#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```

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

import requests import re import time import hashlib def get_page(url): print('GET %s' %url) try: response=requests.get(url) if response.status_code == 200: return response.content except Exception: pass def parse_index(res): obj=re.compile('class="items.*?<a href="(.*?)"',re.S) detail_urls=obj.findall(res.decode('gbk')) for detail_url in detail_urls: if not detail_url.startswith('http'): detail_url='http://www.xiaohuar.com'+detail_url yield detail_url def parse_detail(res): obj=re.compile('id="media".*?src="(.*?)"',re.S) res=obj.findall(res.decode('gbk')) if len(res) > 0: movie_url=res[0] return movie_url def save(movie_url): response=requests.get(movie_url,stream=False) if response.status_code == 200: m=hashlib.md5() m.update(('%s%s.mp4' %(movie_url,time.time())).encode('utf-8')) filename=m.hexdigest() with open(r'./movies/%s.mp4' %filename,'wb') as f: f.write(response.content) f.flush() def main(): index_url='http://www.xiaohuar.com/list-3-{0}.html' for i in range(5): print('*'*50,i) #爬取主頁面 index_page=get_page(index_url.format(i,)) #解析主頁面,拿到視頻所在的地址列表 detail_urls=parse_index(index_page) #循環爬取視頻頁 for detail_url in detail_urls: #爬取視頻頁 detail_page=get_page(detail_url) #拿到視頻的url movie_url=parse_detail(detail_page) if movie_url: #保存視頻 save(movie_url) if __name__ == '__main__': main() #並發爬取 from concurrent.futures import ThreadPoolExecutor import queue import requests import re import time import hashlib from threading import current_thread p=ThreadPoolExecutor(50) def get_page(url): print('%s GET %s' %(current_thread().getName(),url)) try: response=requests.get(url) if response.status_code == 200: return response.content except Exception as e: print(e) def parse_index(res): print('%s parse index ' %current_thread().getName()) res=res.result() obj=re.compile('class="items.*?<a href="(.*?)"',re.S) detail_urls=obj.findall(res.decode('gbk')) for detail_url in detail_urls: if not detail_url.startswith('http'): detail_url='http://www.xiaohuar.com'+detail_url p.submit(get_page,detail_url).add_done_callback(parse_detail) def parse_detail(res): print('%s parse detail ' %current_thread().getName()) res=res.result() obj=re.compile('id="media".*?src="(.*?)"',re.S) res=obj.findall(res.decode('gbk')) if len(res) > 0: movie_url=res[0] print('MOVIE_URL: ',movie_url) with open('db.txt','a') as f: f.write('%s\n' %movie_url) # save(movie_url) p.submit(save,movie_url) print('%s下載任務已經提交' %movie_url) def save(movie_url): print('%s SAVE: %s' %(current_thread().getName(),movie_url)) try: response=requests.get(movie_url,stream=False) if response.status_code == 200: m=hashlib.md5() m.update(('%s%s.mp4' %(movie_url,time.time())).encode('utf-8')) filename=m.hexdigest() with open(r'./movies/%s.mp4' %filename,'wb') as f: f.write(response.content) f.flush() except Exception as e: print(e) def main(): index_url='http://www.xiaohuar.com/list-3-{0}.html' for i in range(5): p.submit(get_page,index_url.format(i,)).add_done_callback(parse_index) if __name__ == '__main__': main()