項目介紹
使用python抓取京東商城商品(以手機為例)的詳細信息,並將相應的圖片下載下載保存到本地。
爬取步驟
1.選取種子URL:http://list.jd.com/list.html?cat=9987,653,655
2.使用urllib和urllib2下載網頁
3.使用BeautifulSoup和re正則表達式解析html
4.保存數據
工具
python2.7
演示效果:
下載的圖片:
下載示例:
名稱: 摩托羅拉 Moto Z(XT1650-05) 模塊化手機 流金黑 移動聯通電信4G手機 雙卡雙待
京東價格: 3999.00
市場價格: 4299.00
產品編碼:3499302
分辨率:2560×1440(Quad HD / 2K )
后置攝像頭:1300萬像素
前置攝像頭:500萬像素
核 數:四核
頻 率:-
商品名稱:摩托羅拉Moto Z(XT1650-05)
商品編號:3499302
商品毛重:490.00g
商品產地:中國大陸
系統:安卓(Android)
運行內存:4GB
購買方式:其他
電池容量:2000mAh-2999mAh
像素:1000-1600萬
機身內存:64GB
熱點:驍龍芯片,雙卡雙待,快速充電,指紋識別,VoLTE,金屬機身,2K屏,支持NFC
品牌 摩托羅拉(Motorola)
型號 XT1650-05
入網型號 XT1650-05
上市年份 2016年
上市月份 9月
機身顏色 黑色前后面板加玫瑰金硬鋁框架
機身長度(mm) 155.3
機身寬度(mm) 75.3
機身厚度(mm) 5.19
機身重量(g) 134
輸入方式 觸控
運營商標志或內容 無
機身材質分類 其他;金屬邊框
機身材質工藝 美國鋁業航空級硬鋁
操作系統 Android
操作系統版本 6.0.1
CPU品牌 驍龍(Snapdragon)
CPU頻率 -
CPU核數 四核
CPU型號 驍龍820(MSM8996)
雙卡機類型 雙卡雙待單通
最大支持SIM卡數量 2個
SIM卡類型 Nano SIM
4G網絡 4G:移動(TD-LTE);4G:聯通(FDD-LTE);4G:電信(FDD-LTE);4G:聯通(TD-LTE)
3G/2G網絡 3G:移動(TD-SCDMA);3G:聯通(WCDMA);3G:電信(CDMA2000);2G:移動聯通(GSM)+電信(CDMA)
4G+(CA) 移動4G+;聯通4G+;電信4G+
高清語音通話(VOLTE) 移動VOLTE
網絡頻率(2G/3G) 2G:GSM 850/900/1800/1900;3G:TD-SCDMA 1900/2000
ROM 64GB
RAM 4GB
RAM類型 LPDDR 4
存儲卡 支持MicroSD(TF)
最大存儲擴展容量 2TB
主屏幕尺寸(英寸) 5.5英寸
分辨率 2560×1440(Quad HD / 2K )
屏幕像素密度(ppi) 540
屏幕材質類型 OLED
觸摸屏類型 電容屏
前置攝像頭 500萬像素
前攝光圈大小 f/2.2
閃光燈 LED燈
攝像頭數量 1個
后置攝像頭 1300萬像素
攝像頭光圈大小 f/1.8
閃光燈 LED燈
拍照特點 數碼變焦;防抖;全景;HDR
電池容量(mAh) 2600
電池類型 鋰電池
電池是否可拆卸 否
充電器 5V/3A
數據傳輸接口 WIFI;NFC;藍牙;WiFi熱點
NFC/NFC模式 其他
耳機接口類型 Type-C
充電接口類型 Type-C
數據線 USB3.0
指紋識別 支持
語音識別 支持
GPS 支持
電子羅盤 支持
陀螺儀 支持
其他 光線感應
常用功能 收音機;錄音;手勢識別;便簽;超大字體;重力感應
源代碼

1 # coding=utf-8 2 3 #導入模塊 4 import urllib2,re,urllib 5 from bs4 import BeautifulSoup 6 import json,time 7 8 9 #定義抓取類 10 class JD: 11 12 #記錄抓取產品個數 13 prodNum = 1 14 #初始化參數 15 def __init__(self,baseurl,page): 16 self.baseurl = baseurl 17 self.page = page 18 #拼裝成url 19 self.url = self.baseurl+'&'+'page='+str(self.page) 20 #獲取html源代碼 21 def getHtml(self,url): 22 #請求抓取對象 23 request = urllib2.Request(url) 24 #響應對象 25 reponse = urllib2.urlopen(request) 26 #讀取源代碼 27 html = reponse.read() 28 #返回源代碼 29 return html 30 #獲取總頁數 31 def getNum(self,html): 32 #封裝成BeautifulSoup對象 33 soup = BeautifulSoup(html) 34 #定位到總頁數節點 35 items = soup.find_all('span',class_='p-skip') 36 #獲取總頁數 37 for item in items: 38 pagenum = item.find('em').find('b').string 39 return pagenum 40 #獲取所有產品id列表 41 def getIds(self,html): 42 #生成匹配規則 43 pattern = re.compile('<a target="_blank" href="//item.jd.com/(.*?).html".*?>') 44 #查詢匹配對象 45 items = re.findall(pattern,html) 46 return items 47 #根據產品id獲取同款產品列表 48 def getIdByItems(self,id): 49 #拼裝成url 50 url = basePd+str(id)+'.html' 51 #調用抓取函數返回源代碼 52 html = self.getHtml(url) 53 # 封裝成BeautifulSoup對象 54 soup = BeautifulSoup(html) 55 #查詢匹配對象 56 items = soup.find('div',class_='dd clearfix') 57 l = [] 58 #生成列表 59 for item in items: 60 pattern = re.compile('href="//item.jd.com/(.*?).html".*?>') 61 id = re.findall(pattern,str(item)) 62 if id: 63 l += id 64 return l 65 66 #獲取產品價格 67 def getPrice(self,id): 68 url = 'http://p.3.cn/prices/mgets?skuIds=J_'+str(id) 69 jsonString = self.getHtml(url) 70 jsonObject = json.loads(jsonString.decode()) 71 price_jd = jsonObject[0]['p'] 72 price_mk = jsonObject[0]['m'] 73 print '京東價格:',str(price_jd) 74 print '市場價格:',str(price_mk) 75 76 #獲取產品圖片 77 def getImg(self,html,subid): 78 pattern = re.compile(r'<img id=.*?data-origin="(.*?)" alt=.*?', re.S) 79 items = re.findall(pattern, html) 80 for item in items: 81 imgurl = 'http:%s' % (item) 82 urllib.urlretrieve(imgurl, 'd:/temp/jdimg/%s.jpg' % (str(subid))) 83 84 #獲取內容 85 def getContent(self,html,subid): 86 soup = BeautifulSoup(html) 87 title = soup.find('div',class_='sku-name') 88 print '\n-----------------第'+ str(JD.prodNum) +'個產品--------------------\n' 89 for t in title: 90 print '名稱: ',t.string 91 time.sleep(1) 92 #價格 93 self.getPrice(subid) 94 #編碼 95 print '產品編碼:%s' % (str(subid)) 96 items1 = soup.find_all('ul',class_='parameter1 p-parameter-list') 97 #商品基本信息 98 for item in items1: 99 p = item.findAll('p') 100 for i in p: 101 print i.string 102 # 商品基本信息 103 items2 = soup.find_all('ul', class_='parameter2 p-parameter-list') 104 for item in items2: 105 p = item.findAll('li') 106 for i in p: 107 print i.string 108 #規格與包裝 109 items3 = soup.find_all('div',class_='Ptable-item') 110 for item in items3: 111 contents1 = item.findAll('dt') 112 contents2 = item.findAll('dd') 113 for i in range(len(contents1)): 114 print contents1[i].string,contents2[i].string 115 JD.prodNum += 1 116 #啟動抓取程序 117 def start(self): 118 html = spider.getHtml(self.url) 119 pageNum = self.getNum(html) 120 print '正在抓取網頁請稍后............' 121 time.sleep(3) 122 print '抓取完畢,本次共抓取',pageNum,'頁。' 123 time.sleep(1) 124 print '正在解析內容.........' 125 #循環1--頁數 126 for page in range(1,int(pageNum)+1): 127 url = self.baseurl+'&'+'page='+str(page) 128 html = self.getHtml(url) 129 ids = self.getIds(html) 130 #循環2--產品列表 131 for id in ids: 132 urlprod = basePd+str(id)+'.html' 133 htmlprod = self.getHtml(urlprod) 134 subids = self.getIdByItems(id) 135 #循環3--產品組列表 136 for subid in subids: 137 urlsubprod = basePd+str(subid)+'.html' 138 subhtml = self.getHtml(urlsubprod) 139 time.sleep(1) 140 self.getContent(subhtml,subid) 141 self.getImg(subhtml,subid) 142 143 #產品列表base頁 144 basePd = 'http://item.jd.com/' 145 #抓取入口URL 146 baseURL = 'http://list.jd.com/list.html?cat=9987,653,655' 147 #生成爬蟲抓取對象 148 spider = JD(baseURL,1) 149 150 #開始抓取 151 spider.start()
爬蟲基礎知識(掌握的可以跳過)
一、網絡爬蟲的基本結構及工作流程
一個通用的網絡爬蟲的框架如圖所示:
網絡爬蟲的基本工作流程如下:
1.首先選取一部分精心挑選的種子URL;
2.將這些URL放入待抓取URL隊列;
3.從待抓取URL隊列中取出待抓取在URL,解析DNS,並且得到主機的ip,並將URL對應的網頁下載下來,存儲進已下載網頁庫中。此外,將這些URL放進已抓取URL隊列。
4.分析已抓取URL隊列中的URL,分析其中的其他URL,並且將URL放入待抓取URL隊列,從而進入下一個循環。
二、從爬蟲的角度對互聯網進行划分
對應的,可以將互聯網的所有頁面分為五個部分:
1.已下載未過期網頁
2.已下載已過期網頁:抓取到的網頁實際上是互聯網內容的一個鏡像與備份,互聯網是動態變化的,一部分互聯網上的內容已經發生了變化,這時,這部分抓取到的網頁就已經過期了。
3.待下載網頁:也就是待抓取URL隊列中的那些頁面
4.可知網頁:還沒有抓取下來,也沒有在待抓取URL隊列中,但是可以通過對已抓取頁面或者待抓取URL對應頁面進行分析獲取到的URL,認為是可知網頁。
5.還有一部分網頁,爬蟲是無法直接抓取下載的。稱為不可知網頁。
三、抓取策略
在爬蟲系統中,待抓取URL隊列是很重要的一部分。待抓取URL隊列中的URL以什么樣的順序排列也是一個很重要的問題,因為這涉及到先抓取那個頁面,后抓取哪個頁面。而決定這些URL排列順序的方法,叫做抓取策略。下面重點介紹幾種常見的抓取策略:
1.深度優先遍歷策略
深度優先遍歷策略是指網絡爬蟲會從起始頁開始,一個鏈接一個鏈接跟蹤下去,處理完這條線路之后再轉入下一個起始頁,繼續跟蹤鏈接。我們以下面的圖為例:
如下遍歷路徑:A-F-G E-H-I B C D
2.寬度優先遍歷策略
寬度優先遍歷策略的基本思路是,將新下載網頁中發現的鏈接直接插入待抓取URL隊列的末尾。也就是指網絡爬蟲會先抓取起始網頁中鏈接的所有網頁,然后再選擇其中的一個鏈接網頁,繼續抓取在此網頁中鏈接的所有網頁。還是以上面的圖為例:
遍歷路徑:A-B-C-D-E-F G H I
3.反向鏈接數策略
反向鏈接數是指一個網頁被其他網頁鏈接指向的數量。反向鏈接數表示的是一個網頁的內容受到其他人的推薦的程度。因此,很多時候搜索引擎的抓取系統會使用這個指標來評價網頁的重要程度,從而決定不同網頁的抓取先后順序。
在真實的網絡環境中,由於廣告鏈接、作弊鏈接的存在,反向鏈接數不能完全等他我那個也的重要程度。因此,搜索引擎往往考慮一些可靠的反向鏈接數。
4.Partial PageRank策略
Partial PageRank算法借鑒了PageRank算法的思想:對於已經下載的網頁,連同待抓取URL隊列中的URL,形成網頁集合,計算每個頁面的PageRank值,計算完之后,將待抓取URL隊列中的URL按照PageRank值的大小排列,並按照該順序抓取頁面。
如果每次抓取一個頁面,就重新計算PageRank值,一種折中方案是:每抓取K個頁面后,重新計算一次PageRank值。但是這種情況還會有一個問題:對於已經下載下來的頁面中分析出的鏈接,也就是我們之前提到的未知網頁那一部分,暫時是沒有PageRank值的。為了解決這個問題,會給這些頁面一個臨時的PageRank值:將這個網頁所有入鏈傳遞進來的PageRank值進行匯總,這樣就形成了該未知頁面的PageRank值,從而參與排序。下面舉例說明:
5.OPIC策略策略
該算法實際上也是對頁面進行一個重要性打分。在算法開始前,給所有頁面一個相同的初始現金(cash)。當下載了某個頁面P之后,將P的現金分攤給所有從P中分析出的鏈接,並且將P的現金清空。對於待抓取URL隊列中的所有頁面按照現金數進行排序。
6.大站優先策略
對於待抓取URL隊列中的所有網頁,根據所屬的網站進行分類。對於待下載頁面數多的網站,優先下載。這個策略也因此叫做大站優先策略。
----------------------------謝謝大家-----------------------------------