自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一名合格的數(shù)據(jù)分析師分享Python網(wǎng)絡(luò)爬蟲二三事(綜合實(shí)戰(zhàn)案例)

開發(fā) 開發(fā)工具
作為一名合格的數(shù)據(jù)分析師,其完整的技術(shù)知識體系必須貫穿數(shù)據(jù)獲取、數(shù)據(jù)存儲、數(shù)據(jù)提取、數(shù)據(jù)分析、數(shù)據(jù)挖掘、數(shù)據(jù)可視化等各大部分。

接上篇文章《一名合格的數(shù)據(jù)分析師分享Python網(wǎng)絡(luò)爬蟲二三事》

[[184074]]

五、綜合實(shí)戰(zhàn)案例

1. 爬取靜態(tài)網(wǎng)頁數(shù)據(jù)

(1)需求

爬取豆瓣網(wǎng)出版社名字并分別存儲到excel、txt與MySQL數(shù)據(jù)庫中。

(2)分析

  • 查看源碼
  • Ctrl+F搜索任意出版社名字,如博集天卷
  • 確定正則模式
  1. "<div class="name">(.*?)</div>"  

(3)思路

  • 下載目標(biāo)頁面
  • 正則匹配目標(biāo)內(nèi)容
  • Python列表存儲
  • 寫入Excel/txt/MySQL

(4)源碼

  1. ''信息存儲'''import urllibimport reimport xlsxwriterimport MySQLdb#-----------------(1)存儲到excel與txt-------------------------#def gxls_concent(target_url,pat): 
  2.     ''' 
  3. 功能:爬取數(shù)據(jù) 
  4.     @target_url:爬取目標(biāo)網(wǎng)址 
  5.     @pat:數(shù)據(jù)過濾模式 
  6.     ''' 
  7.     data = urllib.request.urlopen(target_url).read() 
  8.     reret_concent = re.compile(pat).findall(str(data,'utf-8')) 
  9.     return ret_concentdef wxls_concent(ret_xls,ret_concent): 
  10.     ''' 
  11.     功能:將最終結(jié)果寫入douban.xls中 
  12.     @ret_xls:最終結(jié)果存儲excel表的路徑 
  13.     @ret_concent:爬取數(shù)據(jù)結(jié)果列表 
  14.     ''' 
  15.     # 打開最終寫入的文件 
  16.     wb1 = xlsxwriter.Workbook(ret_xls) 
  17.     # 創(chuàng)建一個sheet工作對象 
  18.     ws = wb1.add_worksheet() 
  19.     try: 
  20.         for i in range(len(ret_concent)): 
  21.             data = ret_concent[i] 
  22.             ws.write(i,0,data) 
  23.         wb1.close() 
  24.     except Exception as er: 
  25.         print('寫入“'+ret_xls+'”文件時出現(xiàn)錯誤') 
  26.         print(er)    def wtxt_concent(ret_txt,ret_concent): 
  27.     ''' 
  28.     功能:將最終結(jié)果寫入douban.txt中 
  29.     @ret_xls:最終結(jié)果存儲excel表的路徑 
  30.     @ret_concent:爬取數(shù)據(jù)結(jié)果列表 
  31.     ''' 
  32.     fh = open(ret_txt,"wb") 
  33.     try: 
  34.         for i in range(len(ret_concent)): 
  35.             data = ret_concent[i] 
  36.             datadata = data+"\r\n" 
  37.             datadata = data.encode() 
  38.             fh.write(data) 
  39.     except Exception as er: 
  40.         print('寫入“'+ret_txt+'”文件時出現(xiàn)錯誤') 
  41.         print(er)   
  42.     fh.close()def mainXlsTxt(): 
  43.     ''' 
  44.     功能:將數(shù)據(jù)存儲到excel表中 
  45.     ''' 
  46.     target_url = 'https://read.douban.com/provider/all'  # 爬取目標(biāo)網(wǎng)址 
  47.     pat = '<div>(.*?)</div>' # 爬取模式 
  48.     ret_xls = "F:/spider_ret/douban.xls"   # excel文件路徑 
  49.     ret_txt = "F:/spider_ret/douban.txt"   # txt文件路徑 
  50.     ret_concent = gxls_concent(target_url,pat) # 獲取數(shù)據(jù) 
  51.     wxls_concent(ret_xls,ret_concent) # 寫入excel表 
  52.     wtxt_concent(ret_txt,ret_concent) # 寫入txt文件  #---------------------END(1)--------------------------------##-------------------(2)存儲到MySQL---------------------------#def db_con(): 
  53.     ''' 
  54.     功能:連接MySQL數(shù)據(jù)庫 
  55.     ''' 
  56.     con = MySQLdb.connect( 
  57.         host='localhost',  # port 
  58.         user='root',       # usr_name 
  59.         passwd='xxxx',     # passname 
  60.         db='urllib_data',  # db_name 
  61.         charset='utf8'
  62.         local_infile = 1 
  63.         ) 
  64.     return con   def exeSQL(sql): 
  65.     ''' 
  66. 功能:數(shù)據(jù)庫查詢函數(shù) 
  67.     @sql:定義SQL語句 
  68.     ''' 
  69.     print("exeSQL: " + sql) 
  70.     #連接數(shù)據(jù)庫 
  71.     con = db_con() 
  72.     con.query(sql)   def gdb_concent(target_url,pat): 
  73.     ''' 
  74.     功能:轉(zhuǎn)換爬取數(shù)據(jù)為插入數(shù)據(jù)庫格式:[[value_1],[value_2],...,[value_n]] 
  75.     @target_url:爬取目標(biāo)網(wǎng)址 
  76.     @pat:數(shù)據(jù)過濾模式 
  77.     ''' 
  78.     tmp_concent = gxls_concent(target_url,pat) 
  79.     ret_concent = []    
  80.     for i in range(len(tmp_concent)): 
  81.         ret_concent.append([tmp_concent[i]]) 
  82.     return ret_concentdef wdb_concent(tbl_name,ret_concent): 
  83.     ''' 
  84.     功能:將爬取結(jié)果寫入MySQL數(shù)據(jù)庫中 
  85.     @tbl_name:數(shù)據(jù)表名 
  86.     @ret_concent:爬取數(shù)據(jù)結(jié)果列表 
  87.     ''' 
  88.     exeSQL("drop table if exists " + tbl_name) 
  89.     exeSQL("create table " + tbl_name + "(pro_name VARCHAR(100));") 
  90.     insert_sql = "insert into " + tbl_name + " values(%s);" 
  91.     con = db_con() 
  92.     cursor = con.cursor() 
  93.     try: 
  94.         cursor.executemany(insert_sql,ret_concent) 
  95.     except Exception as er: 
  96.         print('執(zhí)行MySQL:"' + str(insert_sql) + '"時出錯')         
  97.         print(er) 
  98.     finally: 
  99.         cursor.close()         
  100.         con.commit() 
  101.         con.close()def mainDb(): 
  102.     ''' 
  103.     功能:將數(shù)據(jù)存儲到MySQL數(shù)據(jù)庫中 
  104.     ''' 
  105.     target_url = 'https://read.douban.com/provider/all'  # 爬取目標(biāo)網(wǎng)址 
  106.     pat = '<div>(.*?)</div>' # 爬取模式 
  107.     tbl_name = "provider" # 數(shù)據(jù)表名 
  108.     # 獲取數(shù)據(jù) 
  109.     ret_concent = gdb_concent(target_url,pat) 
  110.     # 寫入MySQL數(shù)據(jù)庫 
  111.     wdb_concent(tbl_name,ret_concent)  #---------------------END(2)--------------------------------#if __name__ == '__main__': 
  112.     mainXlsTxt() 
  113. mainDb() 


(5)結(jié)果

 爬取靜態(tài)網(wǎng)頁數(shù)據(jù)

2. 爬取基于Ajax技術(shù)網(wǎng)頁數(shù)據(jù)

(1)需求

爬取拉勾網(wǎng)廣州的數(shù)據(jù)挖掘崗位信息并存儲到本地Excel文件中

(2)分析

a. 崗位數(shù)據(jù)在哪里?

  • 打開拉勾網(wǎng)==》輸入關(guān)鍵詞“數(shù)據(jù)挖掘”==》查看源碼==》沒發(fā)現(xiàn)崗位信息
  • 打開拉勾網(wǎng)==》輸入關(guān)鍵詞“數(shù)據(jù)挖掘”==》按F12==》Network刷新==》按下圖操作

我們可以發(fā)現(xiàn)存在position和company開頭的json文件,這很可能就是我們所需要的崗位信息,右擊選擇open link in new tab,可以發(fā)現(xiàn)其就是我們所需的內(nèi)容。

右擊選擇open link in new tab

b. 如何實(shí)現(xiàn)翻頁?

我們在寫爬蟲的時候需要多頁爬取,自動模擬換頁操作。首先我們點(diǎn)擊下一頁,可以看到url沒有改變,這也就是Ajax(異步加載)的技術(shù)。點(diǎn)擊position的json文件,在右側(cè)點(diǎn)擊Headers欄,可以發(fā)現(xiàn)***部有如下內(nèi)容:

在右側(cè)點(diǎn)擊Headers欄

當(dāng)我們換頁的時候pn則變?yōu)?且first變?yōu)閒alse,故我們可以通過構(gòu)造post表單進(jìn)行爬取。

c. Json數(shù)據(jù)結(jié)構(gòu)怎么樣?

Json數(shù)據(jù)結(jié)構(gòu)

(3)源碼

  1. import urllib.requestimport urllib.parseimport socketfrom multiprocessing.dummy import Poolimport jsonimport timeimport xlsxwriter#----------------------------------------------------------#######(1)獲取代理IP###def getProxies(): 
  2.   ''' 
  3.   功能:調(diào)用API獲取原始代理IP池 
  4.   ''' 
  5.   url = "http://api.xicidaili.com/free2016.txt" 
  6.   i_headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0"} 
  7.   global proxy_addr 
  8.   proxy_addr = [] 
  9.   try: 
  10.       req = urllib.request.Request(url,headers = i_headers
  11.       proxy = urllib.request.urlopen(req).read() 
  12.       proxyproxy = proxy.decode('utf-8') 
  13.       proxyproxy_addr = proxy.split('\r\n')  #設(shè)置分隔符為換行符 
  14.   except Exception as er: 
  15.       print(er) 
  16.   return proxy_addr   def testProxy(curr_ip): 
  17.   ''' 
  18.   功能:利用百度首頁,逐個驗(yàn)證代理IP的有效性 
  19.   @curr_ip:當(dāng)前被驗(yàn)證的IP 
  20.   ''' 
  21.   socket.setdefaulttimeout(5)  #設(shè)置全局超時時間 
  22.   tarURL = "https://www.baidu.com/"  #測試網(wǎng)址 
  23.   proxy_ip = [] 
  24.   try: 
  25.       proxy_support = urllib.request.ProxyHandler({"http":curr_ip}) 
  26.       opener = urllib.request.build_opener(proxy_support) 
  27.       opener.addheaders=[("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0")] 
  28.       urllib.request.install_opener(opener) 
  29.       res = urllib.request.urlopen(tarURL).read() 
  30.       proxy_ip.append(curr_ip) 
  31.       print(len(res)) 
  32.   except Exception as er: 
  33.       print("驗(yàn)證代理IP("+curr_ip+")時發(fā)生錯誤:"+er) 
  34.   return proxy_ip   def mulTestProxies(proxies_ip): 
  35.   ''' 
  36.   功能:構(gòu)建多進(jìn)程驗(yàn)證所有代理IP 
  37.   @proxies_ip:代理IP池 
  38.   ''' 
  39.   pool = Pool(processes=4)  #開啟四個進(jìn)程 
  40.   proxies_addr = pool.map(testProxy,proxies_ip) 
  41.   pool.close() 
  42.   pool.join()  #等待進(jìn)程池中的worker進(jìn)程執(zhí)行完畢 
  43.   return proxies_addr#----------------------------------------------------------#######(2)爬取數(shù)據(jù)###def getInfoDict(url,page,pos_words_one,proxy_addr_one): 
  44.   ''' 
  45.   功能:獲取單頁職位數(shù)據(jù),返回?cái)?shù)據(jù)字典 
  46.   @url:目標(biāo)URL 
  47.   @page:爬取第幾頁 
  48.   @pos_words_one:搜索關(guān)鍵詞(單個) 
  49.   @proxy_addr_one:使用的代理IP(單個) 
  50.   ''' 
  51.   global pos_dict 
  52.   page = 1 
  53.   i_headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0") 
  54.   proxy = urllib.request.ProxyHandler({"http":proxy_addr_one}) 
  55.   opener = urllib.request.build_opener(proxy,urllib.request.HTTPHandler) 
  56.   opener.addheaders=[i_headers] 
  57.   urllib.request.install_opener(opener) 
  58.   if page==1: 
  59.       tORf = "true" 
  60.   else: 
  61.       tORf = "false" 
  62.   mydata = urllib.parse.urlencode({"first": tORf,            
  63.                                    "pn": page,           #pn變化實(shí)現(xiàn)翻頁 
  64.                                    "kd": pos_words_one } ).encode("utf-8") 
  65.   try: 
  66.       req = urllib.request.Request(url,mydata) 
  67.       data=urllib.request.urlopen(req).read().decode("utf-8","ignore")  #利用代理ip打開 
  68.       pos_dict = json.loads(data)  #將str轉(zhuǎn)成dict 
  69.   except urllib.error.URLError  as er: 
  70.       if hasattr(er,"code"): 
  71.           print("獲取職位信息json對象時發(fā)生URLError錯誤,錯誤代碼:") 
  72.           print(er.code) 
  73.       if hasattr(er,"reason"): 
  74.           print("獲取職位信息json對象時發(fā)生URLError錯誤,錯誤原因:") 
  75.           print(er.reason) 
  76.   return pos_dictdef getInfoList(pos_dict): 
  77.   ''' 
  78.   功能:將getInfoDict()返回的數(shù)據(jù)字典轉(zhuǎn)換為數(shù)據(jù)列表 
  79.   @pos_dict:職位信息數(shù)據(jù)字典 
  80.   ''' 
  81.   pos_list = []  #職位信息列表    
  82.   jcontent = pos_dict["content"]["positionResult"]["result"]     
  83.   for i in jcontent:         
  84.       one_info = []  #一個職位的相關(guān)信息       
  85.       one_info.append(i["companyFullName"])         
  86.       one_info.append(i['companySize'])         
  87.       one_info.append(i['positionName'])         
  88.       one_info.append(i['education'])         
  89.       one_info.append(i['financeStage'])         
  90.       one_info.append(i['salary'])         
  91.       one_info.append(i['city'])         
  92.       one_info.append(i['district'])         
  93.       one_info.append(i['positionAdvantage'])         
  94.       one_info.append(i['workYear'])         
  95.       pos_list.append(one_info) 
  96.   return pos_listdef getPosInfo(pos_words,city_words,proxy_addr): 
  97.   ''' 
  98.   功能:基于函數(shù)getInfoDict()與getInfoList(),循環(huán)遍歷每一頁獲取最終所有職位信息列表 
  99.   @pos_words:職位關(guān)鍵詞(多個) 
  100.   @city_words:限制城市關(guān)鍵詞(多個) 
  101.   @proxy_addr:使用的代理IP池(多個) 
  102.   ''' 
  103.   posInfo_result = []     
  104.   title = ['公司全名', '公司規(guī)模', '職位名稱', '教育程度', '融資情況', "薪資水平", "城市", "區(qū)域", "優(yōu)勢", "工作經(jīng)驗(yàn)"]     
  105.   posInfo_result.append(title)   
  106.   for i in range(0,len(city_words)): 
  107.       #i = 0 
  108.       key_city = urllib.request.quote(city_words[i]) 
  109.       #篩選關(guān)鍵詞設(shè)置:gj=應(yīng)屆畢業(yè)生&xl=大專&jd=成長型&hy=移動互聯(lián)網(wǎng)&px=new&city=廣州 
  110.       url = "https://www.lagou.com/jobs/positionAjax.json?city="+key_city+"&needAddtionalResult=false
  111.       for j in range(0,len(pos_words)): 
  112.           #j = 0 
  113.           page=1 
  114.           while page<10:  #每個關(guān)鍵詞搜索拉鉤顯示30頁,在此只爬取10頁 
  115.               pos_wordspos_words_one = pos_words[j] 
  116.               #k = 1 
  117.               proxy_addrproxy_addr_one = proxy_addr[page] 
  118.               #page += 1 
  119.               time.sleep(3) 
  120.               pos_info = getInfoDict(url,page,pos_words_one,proxy_addr_one)  #獲取單頁信息列表 
  121.               pos_infoList = getInfoList(pos_info) 
  122.               posInfo_result += pos_infoList  #累加所有頁面信息        
  123.               page += 1    
  124.   return posInfo_result#----------------------------------------------------------#######(3)存儲數(shù)據(jù)###def wXlsConcent(export_path,posInfo_result): 
  125.   ''' 
  126.   功能:將最終結(jié)果寫入本地excel文件中 
  127.   @export_path:導(dǎo)出路徑 
  128.   @posInfo_result:爬取的數(shù)據(jù)列表 
  129.   ''' 
  130.   # 打開最終寫入的文件 
  131.   wb1 = xlsxwriter.Workbook(export_path) 
  132.   # 創(chuàng)建一個sheet工作對象 
  133.   ws = wb1.add_worksheet() 
  134.   try: 
  135.       for i in range(0,len(posInfo_result)): 
  136.           for j in range(0,len(posInfo_result[i])): 
  137.               data = posInfo_result[i][j] 
  138.               ws.write(i,j,data) 
  139.       wb1.close() 
  140.   except Exception as er: 
  141.       print('寫入“'+export_path+'”文件時出現(xiàn)錯誤:') 
  142.       print(er)#----------------------------------------------------------#######(4)定義main()函數(shù)###def main(): 
  143.   ''' 
  144.   功能:主函數(shù),調(diào)用相關(guān)函數(shù),最終輸出路徑(F:/spider_ret)下的positionInfo.xls文件     
  145.   ''' 
  146.   #---(1)獲取代理IP池 
  147.   proxies = getProxies()  #獲取原始代理IP    
  148.   proxy_addr = mulTestProxies(proxies) #多線程測試原始代理IP 
  149.   #---(2)爬取數(shù)據(jù) 
  150.   search_key = ["數(shù)據(jù)挖掘"]  #設(shè)置職位關(guān)鍵詞(可以設(shè)置多個) 
  151.   city_word = ["廣州"]  #設(shè)置搜索地區(qū)(可以設(shè)置多個) 
  152.   posInfo_result = getPosInfo(search_key,city_word,proxy_addr) #爬取職位信息 
  153.   #---(3)存儲數(shù)據(jù) 
  154.   export_path = "F:/spider_ret/positionInfo.xls" #設(shè)置導(dǎo)出路徑 
  155.   wXlsConcent(export_path,posInfo_result)  #寫入到excel中           if __name__ == "__main__": 
  156.   main() 

接下篇文章《一名合格的數(shù)據(jù)分析師分享Python網(wǎng)絡(luò)爬蟲二三事(Scrapy自動爬蟲)》

【本文是51CTO專欄機(jī)構(gòu)“豈安科技”的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(bigsec)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2017-02-23 17:46:11

數(shù)據(jù)分析師Python網(wǎng)絡(luò)爬蟲

2017-02-23 18:41:03

數(shù)據(jù)分析師Python網(wǎng)絡(luò)爬蟲

2015-08-04 13:25:46

數(shù)據(jù)分析

2014-06-19 14:00:46

數(shù)據(jù)分析師

2017-12-11 15:56:44

數(shù)據(jù)分析師數(shù)據(jù)倉庫數(shù)據(jù)源

2017-09-19 13:35:47

數(shù)據(jù)科學(xué)數(shù)據(jù)分析python

2016-11-11 20:38:39

數(shù)據(jù)分析師大數(shù)據(jù)

2012-06-08 10:12:08

架構(gòu)師

2013-04-11 10:03:55

2012-08-08 09:00:29

數(shù)據(jù)分析師

2015-08-18 13:26:05

數(shù)據(jù)分析

2015-09-30 09:36:58

數(shù)據(jù)分析師面試offer

2016-10-21 14:41:22

數(shù)據(jù)分析師大數(shù)據(jù)

2013-07-29 15:58:28

大數(shù)據(jù)數(shù)據(jù)分析

2017-02-13 19:25:24

2015-04-03 11:19:21

大數(shù)據(jù)大數(shù)據(jù)分析師

2022-11-11 11:35:14

2012-08-07 17:32:25

數(shù)據(jù)分析師

2023-08-25 16:33:10

2015-08-17 09:39:40

大數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號