天想跟大家分享的是關于網絡爬蟲的相關知識,網絡爬蟲是一種根據一定的規則,自動地對互聯網上相關內容進行抓取的程序或者腳本,本文的內容主要是通過分析京東評論的加載過程,獲取相關API,然后通過使用基于Python語言的開源網絡爬蟲框架——Scrapy,大量獲取相關評論內容。
本文假定讀者具有一定的Python編程經驗,具有少量HTTP協議和HTML的相關知識,對爬蟲的工作原理有一定了解。
在開始編寫爬蟲之前,我們需要獲得啟動爬蟲所需要的相關鏈接。在本文,我們將以對京東鞋類評論爬取為例,進行說明(其他種類爬取流程類似,區別只在于數據處理)。
首先打開京東,搜索“鞋”,打開任意一件商品,并切換到“商品評價”標簽頁,如圖所示。
啟用瀏覽器的網頁分析功能,以Safari瀏覽器為例,右鍵點擊網頁任意部分,選擇”檢查元素“,切換到“網絡”標簽下,如果有其他內容的話,可以點擊右側的垃圾桶圖標清空歷史,如圖所示。
然后我們點擊評論區的換頁按鈕,切換到任意一頁新的評論,此時可以發現瀏覽器對本次點擊產生的數據交換過程進行了記錄,我們發現其中有一條名為”productPageComments.action”的記錄,對其進行分析可以看到對應的完整URL,如圖所示。
其完整URL為:https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv6630&productId=10353518575&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0
顯而易見,評論的加載是通過GET請求實現,對我們來說,該URL中最關鍵的GET參數為productID和page,它們分別定義了對應的商品編號以及評論頁碼。通過訪問該URL,我們可以得到內容如圖所示。
可以看到,該URL返回的內容為json數據包,同時以請求中callback定義的函數名對其進行包裹,這一點從整個數據包最前方可以看出。我們將GET請求中callback參數去掉以后即可得到原始的json數據包,如圖所示。
因此,在不考慮其他參數的情況下,我們需要的API格式為:https://club.jd.com/comment/productPageComments.action?productId={}&score=0&sortType=5&page={}&pageSize=10&isShadowSku=0
至此,我們獲得了返回任意商品的任意評論頁的API,下面我們將對API返回數據本身的內容進行分析。
從前面圖中可以看出,API返回數據應該是一個字典,我們通過使用requests獲得API返回字典以及Python的json模塊進行分析。
其中對我們來說最重要的是鍵comments所對應的值,值為一個列表,其中每個元素為一個字典,存放的是每一條評論的相關信息。
根據實際需要,在本次實現中選取了以下信息:
guid –> 評論用戶id
id –> 該評論id
referenceId –> 評論商品id
creationTime –> 評論時間
score –> 評論評分
userProvince –> 評論用戶歸屬地
userLevelName –> 評論用戶會員級別
productColor –> 評論用戶購買顏色
productSize –> 評論用戶購買尺寸
至此,我們完成了對API返回字典的分析,在構建Scrapy爬蟲之前,我們還需要對商品列表進行分析。
我們已經擁有對任意給定的商品id,獲取其所有評論的API,但在構建爬蟲之前,我們還有最后一個問題,如何獲得商品id?
我們可以很容易的獲得并格式化京東的搜索鏈接:https://search.jd.com/Search?keyword={}&enc=utf-8&page={},根據該格式化鏈接,我們只需要填寫搜索關鍵字以及搜索頁碼就能得到對應頁的搜索結果。通過對網頁源代碼進行分析,可以發現每個商品都處于class="gl-item"的li元素下,如圖所示。
我們只需要對class="gl-item"的li元素下class="p-img"的div元素下的a元素的href屬性進行提取處理即可得到商品id,如圖中的10353518575。
至此,我們完成了對商品列表的分析工作,接下來我們將構建基于Scrapy的爬蟲來完成對評論的爬取工作。
我們在上節中獲得了商品的詳細信息鏈接,如:https://item.jd.com/10353518575.html,我們可以對該頁面內容進行爬取以獲得更全面的商品信息。在這部分需要注意的是,很多內容是通過JavaScript進行動態加載的,在爬取時需要注意,否則得到的數據并不符合需要。通過啟用瀏覽器的“停用JavaScript”功能,可以看到在不執行JavaScript時的頁面是什么樣的,如圖所示。
可以看到,商品的價格等信息是沒有進行加載的,所以如果需要對價格進行爬取,需要使用到selenium等工具來完成瀏覽器的模擬或者進一步分析JavaScript的執行邏輯。
Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。其最初是為了網絡抓取所設計的,也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。
要使用Scrapy,首先得建立項目:
$ scrapy startproject jd New Scrapy project 'jd', using template directory '/usr/local/lib/python3.6/site-packages/scrapy/templates/project', created in: /private/tmp/jd You can start your first spider with: cd jd scrapy genspider example example.com
在建好的jd文件夾下,有一個jd文件夾以及一個scrapy.cfg文件,進入前者,可以看到以下內容:
$ ls __init__.py items.py pipelines.py spiders __pycache__ middlewares.py settings.py
其中:
items.py –> 完成數據容器Item的定義
爬取的主要目標就是從非結構性的數據源提取結構性數據,例如網頁。Scrapy提供 Item 類來滿足這樣的需求。Item 對象是種簡單的容器,保存了爬取到得數據。 其提供了 類似于詞典(dictionary-like) 的API以及用于聲明可用字段的簡單語法。
pipelines.py –> 完成對Item處理流水線的定義
當Item在Spider中被收集之后,它將會被傳遞到Item Pipeline,一些組件會按照一定的順序執行對Item的處理。每個item pipeline組件(有時稱之為“Item Pipeline”)是實現了簡單方法的Python類。他們接收到Item并通過它執行一些行為,同時也決定此Item是否繼續通過pipeline,或是被丟棄而不再進行處理。
以下是item pipeline的一些典型應用:
清理HTML數據
驗證爬取的數據(檢查item包含某些字段)
查重(并丟棄)
將爬取結果保存到數據庫中
middlewares.py –> 完成Spider中間件的定義
Spider中間件是介入到Scrapy的spider處理機制的鉤子框架,通過定義并使用中間件,可以對發送給Spiders的response以及Spiders產生的Request對象進行處理。
settings.py –> 完成對爬蟲的控制
Scrapy settings提供了定制Scrapy組件的方法。通過修改settings.py,可以控制包括核心(core),插件(extension),pipeline及spider組件。settings為代碼提供了提取以key-value映射的配置值的的全局命名空間(namespace)。settings同時也是選擇當前激活的Scrapy項目的方法。
spiders –> 完成對爬蟲Spider的定義
Spider類定義了如何爬取某個(或某些)網站。包括了爬取的動作(例如:是否跟進鏈接)以及如何從網頁的內容中提取結構化數據(爬取item)。換句話說,Spider就是定義爬取的動作及分析某個網頁(或者是有些網頁)的地方。
定義數據容器items
定義爬蟲類
創建爬蟲類的命令為:
scrapy genspider [爬蟲名] [允許爬取域名]
$ scrapy genspider shoes jd.com Created spider 'shoes' using template 'basic' in module: jd.spiders.shoes
接著打開spiders文件夾下的shoes.py文件進行編輯:
首先我們需要定義一些變量,比如包含搜索關鍵字的列表、格式化搜索鏈接、格式化評論API鏈接等:
然后編輯ShoesSpider類:
詳細分析下這段代碼:
類ShoesSpider繼承自Spider,其余可繼承的類還有CrawlSpider、XMLFeedSpider、SitemapSpider,在這里我們使用了最基本的Spider。
屬性name定義了該爬蟲的名字,在啟動爬蟲的步驟中需要提供爬蟲名字。
屬性allowed_domains定義了一個列表,可以包含一個或多個域名,爬蟲只會對該域名下的鏈接進行爬取。
屬性start_urls定義了一個列表,spider啟動時將從中獲取鏈接進行爬取。
實例方法parse定義了對商品列表頁面進行處理的相關邏輯:
接收一個response參數,該response對象為爬蟲根據Request對象請求獲得的結果。
根據前面幾節的描述,parse方法針對商品列表頁面使用xpath進行分析。
在提取到商品iid后,對該頁面下所有商品iid進行遍歷,分別為商品詳細頁面(可選)以及商品評論頁面構建Request請求,注意使用了yield,因為我們需要返回多個請求而不是一個請求。
對每個Request請求,我們指定了相關參數,比如鏈接、回調函數,以及通過meta關鍵字保存上下文信息字典,這可以在回調函數中訪問Response的meta屬性獲得。
實例方法parse_detail定義了對商品詳細頁面進行處理的相關邏輯:
我們依然通過xpath進行分析,獲得了商品名、商家名、商家評分等信息,使用其實例化ShoeDetailItem類并返回該實例。
實例方法parse_comment定義了對商品評論進行處理的相關邏輯:
根據在Request對象中設置meta屬性,我們可以很方便地獲得當前物品id、當前評論頁碼、以及訪問重試次數。
我們需要對response對象的text屬性使用json.loads進行格式化,但是由于各種原因可能會失敗,所以我們設置了方式重試次數這一變量來控制重試,當本次json.loads格式化失敗,我們會再次進行嘗試訪問該評論鏈接,直到達到最大重試次數10次,然后放棄。
如果解析成功,判斷解析后的字典中鍵comments所對應的內容是否為空,為空代表已經沒有更多評論,則返回。
否則,對每條評論進行遍歷,使用其中的參數實例化ShoeCommentItem類并返回該實例。
在結束評論遍歷后,嘗試對評論下一頁發出Request請求。
至此,我們完成了爬蟲的工作邏輯,接下來需要對流水線進行定義,完成數據的查重以及保存等操作。
定義pipeline流水線
對于各個parse方法返回的Item對象,它們將會被傳遞到在pipelines.py中定義以及settings.py中啟用的流水線中進行處理。
在本文中我們需要對每個Item對象做兩件事,去重以及保存。對于ShoeCommentItem的流水線定義如下:
需要解釋的是類方法from_crawler和實例方法process_item,前者在初始化時會被調用,后者在出現Item
對象時被調用。
對于from_crawler方法:
我們需要忽略之前已經處理過的評論,因此采用了一個set來存儲已經處理過的id
在初始化時,打開之前保存的評論文件shoe_comments.csv,從中獲取id并對seen_ids進行填充
這是一個類方法,需要在最后返回類的實例
對于process_item方法:
方法接收兩個參數,前一個是返回的Item對象,后一個是返回該對象的對應Spider對象
首先判斷了該Item是否是類ShoeCommentItem實例,如果不是的話不進行處理直接返回該對象
提取該對象的id并判斷該對象是否已經處理過,已經處理過的話拋出DropItem異常,停止后續流水線的處理
將該對象id加入seen_ids,并根據val_indices定義的順序將其排序及格式化字符串并追加到shoe_comments.csv中
返回該對象
需要特別注意的是,process_item方法必須返回一個Item(或任何繼承類)對象或者是拋出DropItem
異常,被丟棄的item將不會被之后的pipeline組件所處理,而正常返回的會。
同理我們可以定義ShoeDetailItem的流水線:
該流水線邏輯與前一個類似,在此不再贅述。
settings.py的配置
我們還需要對settings.py進行配置。
其中關鍵的幾個設置是:
CONCURRENT_REQUESTS(并發請求數): 100
COOKIES_ENABLED(啟用cookies): False
ITEM_PIPELINES(item流水線): {‘jd.pipelines.ShoeCommentPipeline’: 300, ‘jd.pipelines.ShoeDetailPipeline’: 301}
具體設置可以根據自己的需求進行設置,以上只是一個示例。
啟動
最后,讓我們啟動這個爬蟲:
$ scrapy crawl shoes
可以在控制臺看到輸出:
2017-03-13 19:21:12 [scrapy.utils.log] INFO: Scrapy 1.3.0 started (bot: jd) 2017-03-13 19:21:12 [scrapy.utils.log] INFO: Overridden settings: {'BOT_NAME': 'jd', 'CONCURRENT_REQUESTS': 100, 'COOKIES_ENABLED': False, 'DOWNLOAD_DELAY': 0.01, 'NEWSPIDER_MODULE': 'jd.spiders', 'SPIDER_MODULES': ['jd.spiders']} 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.logstats.LogStats'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'jd.middlewares.RandomUserAgentMiddleware', 'jd.middlewares.ProxyMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled item pipelines: ['jd.pipelines.ShoeCommentPipeline', 'jd.pipelines.ShoeDetailPipeline'] 2017-03-13 19:21:12 [scrapy.core.engine] INFO: Spider opened 2017-03-13 19:21:12 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-03-13 19:21:12 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023 2017-03-13 19:21:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=3> (referer: None) 2017-03-13 19:21:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=7> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=6> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=9> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=5> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=10> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=2> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=1> (referer: None) 2017-03-13 19:21:16 [scrapy.dupefilters] DEBUG: Filtered duplicate request: <GET http://item.jd.com/10536835318.html> - no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=8> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://item.jd.com/10536835318.html> (referer: https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=6) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> (referer: https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=7) 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 http://item.jd.com/10536835318.html> {'iid': 10536835318, 'name': '她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼', 'scores': '9.72|9.75|9.65|9.63', 'shop': '卡曼鞋類專營店'} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10199823376, 'color': '金黑色.', 'creation_time': '2017-03-10 13:59:31', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '069d0baa-022b-421b-a43a-584f5aa3921e', 'user_level': '銅牌會員', 'user_province': ''} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10175008135, 'color': '金黑色.', 'creation_time': '2017-03-02 12:18:57', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '28dfd6c2-caf2-427d-9927-cf088d3099ea', 'user_level': '銅牌會員', 'user_province': '湖南'} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10163486837, 'color': '金黑色.', 'creation_time': '2017-02-26 15:28:14', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '736ad5a4-9470-4dcc-832d-b59094cf84f4', 'user_level': '銅牌會員', 'user_province': '云南'}
在運行一段時間后,查看shoe_comments.csv和shoe_details.csv內容:
shoe_comments.csv
10199823376,10589923020,069d0baa-022b-421b-a43a-584f5aa3921e,2017-03-10 13:59:31,5,,銅牌會員,金黑色.,36 10175008135,10589923020,28dfd6c2-caf2-427d-9927-cf088d3099ea,2017-03-02 12:18:57,5,湖南,銅牌會員,金黑色.,36 10163486837,10589923020,736ad5a4-9470-4dcc-832d-b59094cf84f4,2017-02-26 15:28:14,5,云南,銅牌會員,金黑色.,36 10205838152,10589923020,93f35818-129f-4aaa-8ea9-549c28a4f791,2017-03-12 14:37:59,5,,注冊會員,金黑色.,36 10175298549,10589923020,fe1a26e0-8cae-43c3-b0d4-c99bf1d961cf,2017-03-02 13:49:07,5,,銅牌會員,金黑色.,36 10205858068,10589923020,65a7243e-7116-4075-b64a-6e8d8d8382a4,2017-03-12 14:44:29,5,,銅牌會員,金黑色.,36 10206280836,10589923020,1d9b5332-5ca6-40be-b408-250606f68c17,2017-03-12 17:00:48,5,,注冊會員,金黑色.,36 10200243913,10589923020,966cda26-ce10-432a-8309-95199ad1903e,2017-03-10 16:15:02,5,,銅牌會員,金黑色.,36 10164313667,10589923020,d09eab89-ed53-47a3-abd1-c897a8bcf694,2017-02-26 20:15:01,5,北京,銅牌會員,金黑色.,36 10162862191,10589923020,ddb58374-f48b-45f9-a2a6-e5e60d53d4ce,2017-02-26 11:42:58,5,,銅牌會員,金黑色.,36 10149921178,11242420873,5f410ce9-fc38-4736-8465-88bbdd7da347,2017-02-21 19:45:56,5,上海,銅牌會員,70060黑色,36 10143787582,11242420873,3f15f14f-1d37-4ccb-befa-9acccd22a3d1,2017-02-19 19:07:20,5,海南,銅牌會員,70060黑色,36 10150729539,11242420873,a601a457-1cef-41c4-955b-3df3dd2646ec,2017-02-22 07:32:52,5,新疆,銅牌會員,70060黑色,36 10147517331,11242420873,b50e1e32-e1fe-4084-b95a-71be8a720950,2017-02-20 23:29:52,5,北京,銅牌會員,70060黑色,36 10147357719,11242420873,fe6ec9de-c39b-4d5e-9cee-bf5926abb465,2017-02-20 22:18:46,5,湖南,銅牌會員,70060黑色,36 10187242860,11242420873,f12f02f7-b378-457f-a501-cdd81f69de6c,2017-03-06 13:53:31,5,云南,銅牌會員,70060黑色,36 10203999129,11242420873,f61e40df-f919-43a2-b876-e81176d59cf9,2017-03-11 20:55:40,5,內蒙古,注冊會員,70060黑色,36 10203827884,11242420873,4a73b3d7-b489-4880-8f8a-bc70015c4e18,2017-03-11 19:55:57,5,浙江,注冊會員,70060黑色,36 10203810598,11242420873,4113c7e0-4556-4aa1-b441-2334bd5419d4,2017-03-11 19:49:51,5,安徽,注冊會員,70060黑色,36 10203802320,11242420873,38a65bba-5284-4190-83f2-1a6a54d57da3,2017-03-11 19:46:57,5,廣西,注冊會員,70060黑色,36
shoe_details.csv
10536835318,她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼,卡曼鞋類專營店,9.72|9.75|9.65|9.63 1587186408,雅詩萊雅休閑鞋女 圓頭深口低幫鞋 拼色厚底女鞋 系帶防水臺女鞋子 GH852Q0紅色 37,宏嘉男鞋專營店,9.79|9.80|9.74|9.76 10536835318,她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼,卡曼鞋類專營店,9.72|9.75|9.65|9.63 11242420873,百芙蓉單鞋女中跟2017春季新款粗跟英倫風小皮鞋女春季新款圓頭深口媽媽工作韓版潮厚底 70060黑色 36,百芙蓉鞋類旗艦店,9.88|9.81|9.83|9.84 11157498264,圓頭深口低幫鞋2017年秋冬新款純色系帶坡跟女鞋防水臺女鞋子 1343黑色 36,馬登爾鞋靴專營店,9.78|9.81|9.75|9.76 10638093860,愛思圖牛津鞋英倫風皮鞋女中跟秋季女鞋粗跟單鞋大頭皮鞋圓頭學生鞋小皮鞋平底鞋潮媽媽鞋女生鞋子 黑色ML6X303 36,愛思圖旗艦店,9.72|9.76|9.71|9.70 10574081025,佩尼泰深口單鞋女頭層牛皮尖頭單鞋中跟粗跟 OL工作職業鞋大小碼女鞋春季新款 灰色 38,佩尼泰旗艦店,9.68|9.73|9.67|9.66 10459020322,瑞蓓妮真皮女鞋2017新款魔術貼深口單鞋女平底舒適休閑鞋大碼防滑中老年媽媽鞋 黑色單鞋 38,瑞蓓妮旗艦店,9.70|9.75|9.65|9.65 11273711543,細跟高跟鞋女2017春季新款尖頭單鞋女深口高跟女士英倫厚底防水臺工作女鞋 紅色 37,家興福鞋業專營店,9.87|9.82|9.80|9.81 11226902308,粗跟單鞋女2017春季新款女鞋OL尖頭高跟鞋深口工作鞋女士皮鞋水鉆百搭鞋子女 DH3658黑色 37,彬度鳥鞋靴旗艦店,9.89|9.83|9.83|9.84 11210447351,她芙 單鞋女2017春季新款單鞋粗跟女鞋子系帶厚底高跟鞋深口學生休閑低幫鞋 綠色 37,她芙旗艦店,9.77|9.77|9.67|9.68 11239261516,AUSDU休閑鞋女圓頭平底深口單鞋粗跟厚底2017春款韓版百搭舒適女鞋媽媽綁帶學生 70030黑色 36,AUSDU鞋類旗艦店,9.87|9.80|9.81|9.82 11267204558,丹芭莎春季女鞋2017新品純色深口鞋女韓版圓頭高跟鞋粗跟防水臺單鞋女潮鞋 M70050黑色 37,丹芭莎旗艦店,9.84|9.81|9.79|9.80 10687936751,fullmir內增高休閑鞋女士小白鞋2016秋季新款厚底鞋韓版潮流低幫學生運動鞋子單鞋 紅 色 37,fullmir鞋類旗艦店,9.61|9.66|9.58|9.58 11167186789,新款單鞋女2017秋季時尚漆皮圓頭低幫休閑鞋秋鞋 工作鞋套腳歐美低跟皮鞋 黑色6119 34,艾琳藝鞋類專營店,9.67|9.79|9.67|9.69 11227438800,意米思時尚女鞋圓頭高跟鞋粗跟媽媽鞋深口單鞋女2017春秋新款韓版百搭小皮鞋防水臺鞋子女 莫70050黑色 36,意米思旗艦店,9.72|9.81|9.79|9.80 11250120847,鄰家天使細跟單鞋2017春季新款尖頭歐美皮鞋深口高跟女鞋春秋款鞋子 LJ619黑色 39標碼,鄰家天使鞋類旗艦店,9.69|9.74|9.65|9.66 11193717829,單鞋女2017春季新款韓版高跟防水臺粗跟女鞋尖頭深口水鉆通勤OL工作小皮鞋女 鄰1231黑色 37,NEB ANGEL梓贏專賣店,9.78|9.78|9.74|9.75 11166169416,金絲兔尖頭單鞋女2017春季新品深口金屬超高跟鞋歐美時尚細跟女鞋百搭小皮鞋工作鞋 黑色 36,金絲兔廣匯達專賣店,9.89|9.83|9.83|9.84 10617152040,ZHR小皮鞋真皮小白鞋女深口單鞋平底護士工作鞋潮 白色 39,零邦鞋靴專營店,9.69|9.68|9.69|9.69 1471841136,寶思特2017春季新款真皮平底平跟休閑女單鞋軟牛皮軟底媽媽鞋花朵跳舞鞋加大碼女鞋子 黑色 39,寶思特旗艦店,9.75|9.74|9.65|9.65 11204372265,霍爾世家 深口單鞋女粗跟高跟鞋2017春季新款英倫風真皮尖頭女鞋防水臺 黑色 37,霍爾世家旗艦店,9.64|9.70|9.63|9.64
至此,我們完成了整個數據的爬取工作。
有經驗的讀者可以看出來,本文完成的爬蟲是較為基礎的爬蟲,不涉及到Scrapy高級的特性,也不涉及到反爬蟲的內容,對于感興趣的讀者,可以從以下幾個方面繼續深入。
由于京東對爬蟲爬取評論并沒有反爬措施,所以本文沒有涉及到反爬的內容,不過在編寫該爬蟲的時候有考慮到這部分內容,所以編寫了中間件來完成User-Agent的隨機設置以及使用代理池來分散請求等簡單的反爬措施,有興趣的讀者可以查閱Github源代碼。
對于較大的爬取工作,可以考慮使用scrapy-redis等工具來構建分布式爬蟲,以增加爬取效率。
在獲得大量的數據之后,可以使用matplotlib等工具對數據進行可視化分析。
以上就是本文的全部內容,有興趣的讀者可以查閱Github并下載源碼,該項目地址: https://github.com/Time1ess/MyCodes/tree/master/scrapy/jd
天想跟大家分享的是關于網絡爬蟲的相關知識,網絡爬蟲是一種根據一定的規則,自動地對互聯網上相關內容進行抓取的程序或者腳本,本文的內容主要是通過分析京東評論的加載過程,獲取相關API,然后通過使用基于Python語言的開源網絡爬蟲框架——Scrapy,大量獲取相關評論內容。
本文假定讀者具有一定的Python編程經驗,具有少量HTTP協議和HTML的相關知識,對爬蟲的工作原理有一定了解。
在開始編寫爬蟲之前,我們需要獲得啟動爬蟲所需要的相關鏈接。在本文,我們將以對京東鞋類評論爬取為例,進行說明(其他種類爬取流程類似,區別只在于數據處理)。
首先打開京東,搜索“鞋”,打開任意一件商品,并切換到“商品評價”標簽頁,如圖所示。
啟用瀏覽器的網頁分析功能,以Safari瀏覽器為例,右鍵點擊網頁任意部分,選擇”檢查元素“,切換到“網絡”標簽下,如果有其他內容的話,可以點擊右側的垃圾桶圖標清空歷史,如圖所示。
然后我們點擊評論區的換頁按鈕,切換到任意一頁新的評論,此時可以發現瀏覽器對本次點擊產生的數據交換過程進行了記錄,我們發現其中有一條名為”productPageComments.action”的記錄,對其進行分析可以看到對應的完整URL,如圖所示。
其完整URL為:https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv6630&productId=10353518575&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0
顯而易見,評論的加載是通過GET請求實現,對我們來說,該URL中最關鍵的GET參數為productID和page,它們分別定義了對應的商品編號以及評論頁碼。通過訪問該URL,我們可以得到內容如圖所示。
可以看到,該URL返回的內容為json數據包,同時以請求中callback定義的函數名對其進行包裹,這一點從整個數據包最前方可以看出。我們將GET請求中callback參數去掉以后即可得到原始的json數據包,如圖所示。
因此,在不考慮其他參數的情況下,我們需要的API格式為:https://club.jd.com/comment/productPageComments.action?productId={}&score=0&sortType=5&page={}&pageSize=10&isShadowSku=0
至此,我們獲得了返回任意商品的任意評論頁的API,下面我們將對API返回數據本身的內容進行分析。
從前面圖中可以看出,API返回數據應該是一個字典,我們通過使用requests獲得API返回字典以及Python的json模塊進行分析。
其中對我們來說最重要的是鍵comments所對應的值,值為一個列表,其中每個元素為一個字典,存放的是每一條評論的相關信息。
根據實際需要,在本次實現中選取了以下信息:
guid –> 評論用戶id
id –> 該評論id
referenceId –> 評論商品id
creationTime –> 評論時間
score –> 評論評分
userProvince –> 評論用戶歸屬地
userLevelName –> 評論用戶會員級別
productColor –> 評論用戶購買顏色
productSize –> 評論用戶購買尺寸
至此,我們完成了對API返回字典的分析,在構建Scrapy爬蟲之前,我們還需要對商品列表進行分析。
我們已經擁有對任意給定的商品id,獲取其所有評論的API,但在構建爬蟲之前,我們還有最后一個問題,如何獲得商品id?
我們可以很容易的獲得并格式化京東的搜索鏈接:https://search.jd.com/Search?keyword={}&enc=utf-8&page={},根據該格式化鏈接,我們只需要填寫搜索關鍵字以及搜索頁碼就能得到對應頁的搜索結果。通過對網頁源代碼進行分析,可以發現每個商品都處于class="gl-item"的li元素下,如圖所示。
我們只需要對class="gl-item"的li元素下class="p-img"的div元素下的a元素的href屬性進行提取處理即可得到商品id,如圖中的10353518575。
至此,我們完成了對商品列表的分析工作,接下來我們將構建基于Scrapy的爬蟲來完成對評論的爬取工作。
我們在上節中獲得了商品的詳細信息鏈接,如:https://item.jd.com/10353518575.html,我們可以對該頁面內容進行爬取以獲得更全面的商品信息。在這部分需要注意的是,很多內容是通過JavaScript進行動態加載的,在爬取時需要注意,否則得到的數據并不符合需要。通過啟用瀏覽器的“停用JavaScript”功能,可以看到在不執行JavaScript時的頁面是什么樣的,如圖所示。
可以看到,商品的價格等信息是沒有進行加載的,所以如果需要對價格進行爬取,需要使用到selenium等工具來完成瀏覽器的模擬或者進一步分析JavaScript的執行邏輯。
Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。其最初是為了網絡抓取所設計的,也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。
要使用Scrapy,首先得建立項目:
$ scrapy startproject jd New Scrapy project 'jd', using template directory '/usr/local/lib/python3.6/site-packages/scrapy/templates/project', created in: /private/tmp/jd You can start your first spider with: cd jd scrapy genspider example example.com
在建好的jd文件夾下,有一個jd文件夾以及一個scrapy.cfg文件,進入前者,可以看到以下內容:
$ ls __init__.py items.py pipelines.py spiders __pycache__ middlewares.py settings.py
其中:
items.py –> 完成數據容器Item的定義
爬取的主要目標就是從非結構性的數據源提取結構性數據,例如網頁。Scrapy提供 Item 類來滿足這樣的需求。Item 對象是種簡單的容器,保存了爬取到得數據。 其提供了 類似于詞典(dictionary-like) 的API以及用于聲明可用字段的簡單語法。
pipelines.py –> 完成對Item處理流水線的定義
當Item在Spider中被收集之后,它將會被傳遞到Item Pipeline,一些組件會按照一定的順序執行對Item的處理。每個item pipeline組件(有時稱之為“Item Pipeline”)是實現了簡單方法的Python類。他們接收到Item并通過它執行一些行為,同時也決定此Item是否繼續通過pipeline,或是被丟棄而不再進行處理。
以下是item pipeline的一些典型應用:
清理HTML數據
驗證爬取的數據(檢查item包含某些字段)
查重(并丟棄)
將爬取結果保存到數據庫中
middlewares.py –> 完成Spider中間件的定義
Spider中間件是介入到Scrapy的spider處理機制的鉤子框架,通過定義并使用中間件,可以對發送給Spiders的response以及Spiders產生的Request對象進行處理。
settings.py –> 完成對爬蟲的控制
Scrapy settings提供了定制Scrapy組件的方法。通過修改settings.py,可以控制包括核心(core),插件(extension),pipeline及spider組件。settings為代碼提供了提取以key-value映射的配置值的的全局命名空間(namespace)。settings同時也是選擇當前激活的Scrapy項目的方法。
spiders –> 完成對爬蟲Spider的定義
Spider類定義了如何爬取某個(或某些)網站。包括了爬取的動作(例如:是否跟進鏈接)以及如何從網頁的內容中提取結構化數據(爬取item)。換句話說,Spider就是定義爬取的動作及分析某個網頁(或者是有些網頁)的地方。
定義數據容器items
定義爬蟲類
創建爬蟲類的命令為:
scrapy genspider [爬蟲名] [允許爬取域名]
$ scrapy genspider shoes jd.com Created spider 'shoes' using template 'basic' in module: jd.spiders.shoes
接著打開spiders文件夾下的shoes.py文件進行編輯:
首先我們需要定義一些變量,比如包含搜索關鍵字的列表、格式化搜索鏈接、格式化評論API鏈接等:
然后編輯ShoesSpider類:
詳細分析下這段代碼:
類ShoesSpider繼承自Spider,其余可繼承的類還有CrawlSpider、XMLFeedSpider、SitemapSpider,在這里我們使用了最基本的Spider。
屬性name定義了該爬蟲的名字,在啟動爬蟲的步驟中需要提供爬蟲名字。
屬性allowed_domains定義了一個列表,可以包含一個或多個域名,爬蟲只會對該域名下的鏈接進行爬取。
屬性start_urls定義了一個列表,spider啟動時將從中獲取鏈接進行爬取。
實例方法parse定義了對商品列表頁面進行處理的相關邏輯:
接收一個response參數,該response對象為爬蟲根據Request對象請求獲得的結果。
根據前面幾節的描述,parse方法針對商品列表頁面使用xpath進行分析。
在提取到商品iid后,對該頁面下所有商品iid進行遍歷,分別為商品詳細頁面(可選)以及商品評論頁面構建Request請求,注意使用了yield,因為我們需要返回多個請求而不是一個請求。
對每個Request請求,我們指定了相關參數,比如鏈接、回調函數,以及通過meta關鍵字保存上下文信息字典,這可以在回調函數中訪問Response的meta屬性獲得。
實例方法parse_detail定義了對商品詳細頁面進行處理的相關邏輯:
我們依然通過xpath進行分析,獲得了商品名、商家名、商家評分等信息,使用其實例化ShoeDetailItem類并返回該實例。
實例方法parse_comment定義了對商品評論進行處理的相關邏輯:
根據在Request對象中設置meta屬性,我們可以很方便地獲得當前物品id、當前評論頁碼、以及訪問重試次數。
我們需要對response對象的text屬性使用json.loads進行格式化,但是由于各種原因可能會失敗,所以我們設置了方式重試次數這一變量來控制重試,當本次json.loads格式化失敗,我們會再次進行嘗試訪問該評論鏈接,直到達到最大重試次數10次,然后放棄。
如果解析成功,判斷解析后的字典中鍵comments所對應的內容是否為空,為空代表已經沒有更多評論,則返回。
否則,對每條評論進行遍歷,使用其中的參數實例化ShoeCommentItem類并返回該實例。
在結束評論遍歷后,嘗試對評論下一頁發出Request請求。
至此,我們完成了爬蟲的工作邏輯,接下來需要對流水線進行定義,完成數據的查重以及保存等操作。
定義pipeline流水線
對于各個parse方法返回的Item對象,它們將會被傳遞到在pipelines.py中定義以及settings.py中啟用的流水線中進行處理。
在本文中我們需要對每個Item對象做兩件事,去重以及保存。對于ShoeCommentItem的流水線定義如下:
需要解釋的是類方法from_crawler和實例方法process_item,前者在初始化時會被調用,后者在出現Item
對象時被調用。
對于from_crawler方法:
我們需要忽略之前已經處理過的評論,因此采用了一個set來存儲已經處理過的id
在初始化時,打開之前保存的評論文件shoe_comments.csv,從中獲取id并對seen_ids進行填充
這是一個類方法,需要在最后返回類的實例
對于process_item方法:
方法接收兩個參數,前一個是返回的Item對象,后一個是返回該對象的對應Spider對象
首先判斷了該Item是否是類ShoeCommentItem實例,如果不是的話不進行處理直接返回該對象
提取該對象的id并判斷該對象是否已經處理過,已經處理過的話拋出DropItem異常,停止后續流水線的處理
將該對象id加入seen_ids,并根據val_indices定義的順序將其排序及格式化字符串并追加到shoe_comments.csv中
返回該對象
需要特別注意的是,process_item方法必須返回一個Item(或任何繼承類)對象或者是拋出DropItem
異常,被丟棄的item將不會被之后的pipeline組件所處理,而正常返回的會。
同理我們可以定義ShoeDetailItem的流水線:
該流水線邏輯與前一個類似,在此不再贅述。
settings.py的配置
我們還需要對settings.py進行配置。
其中關鍵的幾個設置是:
CONCURRENT_REQUESTS(并發請求數): 100
COOKIES_ENABLED(啟用cookies): False
ITEM_PIPELINES(item流水線): {‘jd.pipelines.ShoeCommentPipeline’: 300, ‘jd.pipelines.ShoeDetailPipeline’: 301}
具體設置可以根據自己的需求進行設置,以上只是一個示例。
啟動
最后,讓我們啟動這個爬蟲:
$ scrapy crawl shoes
可以在控制臺看到輸出:
2017-03-13 19:21:12 [scrapy.utils.log] INFO: Scrapy 1.3.0 started (bot: jd) 2017-03-13 19:21:12 [scrapy.utils.log] INFO: Overridden settings: {'BOT_NAME': 'jd', 'CONCURRENT_REQUESTS': 100, 'COOKIES_ENABLED': False, 'DOWNLOAD_DELAY': 0.01, 'NEWSPIDER_MODULE': 'jd.spiders', 'SPIDER_MODULES': ['jd.spiders']} 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.logstats.LogStats'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'jd.middlewares.RandomUserAgentMiddleware', 'jd.middlewares.ProxyMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled item pipelines: ['jd.pipelines.ShoeCommentPipeline', 'jd.pipelines.ShoeDetailPipeline'] 2017-03-13 19:21:12 [scrapy.core.engine] INFO: Spider opened 2017-03-13 19:21:12 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-03-13 19:21:12 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023 2017-03-13 19:21:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=3> (referer: None) 2017-03-13 19:21:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=7> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=6> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=9> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=5> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=10> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=2> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=1> (referer: None) 2017-03-13 19:21:16 [scrapy.dupefilters] DEBUG: Filtered duplicate request: <GET http://item.jd.com/10536835318.html> - no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=8> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://item.jd.com/10536835318.html> (referer: https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=6) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> (referer: https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=7) 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 http://item.jd.com/10536835318.html> {'iid': 10536835318, 'name': '她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼', 'scores': '9.72|9.75|9.65|9.63', 'shop': '卡曼鞋類專營店'} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10199823376, 'color': '金黑色.', 'creation_time': '2017-03-10 13:59:31', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '069d0baa-022b-421b-a43a-584f5aa3921e', 'user_level': '銅牌會員', 'user_province': ''} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10175008135, 'color': '金黑色.', 'creation_time': '2017-03-02 12:18:57', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '28dfd6c2-caf2-427d-9927-cf088d3099ea', 'user_level': '銅牌會員', 'user_province': '湖南'} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10163486837, 'color': '金黑色.', 'creation_time': '2017-02-26 15:28:14', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '736ad5a4-9470-4dcc-832d-b59094cf84f4', 'user_level': '銅牌會員', 'user_province': '云南'}
在運行一段時間后,查看shoe_comments.csv和shoe_details.csv內容:
shoe_comments.csv
10199823376,10589923020,069d0baa-022b-421b-a43a-584f5aa3921e,2017-03-10 13:59:31,5,,銅牌會員,金黑色.,36 10175008135,10589923020,28dfd6c2-caf2-427d-9927-cf088d3099ea,2017-03-02 12:18:57,5,湖南,銅牌會員,金黑色.,36 10163486837,10589923020,736ad5a4-9470-4dcc-832d-b59094cf84f4,2017-02-26 15:28:14,5,云南,銅牌會員,金黑色.,36 10205838152,10589923020,93f35818-129f-4aaa-8ea9-549c28a4f791,2017-03-12 14:37:59,5,,注冊會員,金黑色.,36 10175298549,10589923020,fe1a26e0-8cae-43c3-b0d4-c99bf1d961cf,2017-03-02 13:49:07,5,,銅牌會員,金黑色.,36 10205858068,10589923020,65a7243e-7116-4075-b64a-6e8d8d8382a4,2017-03-12 14:44:29,5,,銅牌會員,金黑色.,36 10206280836,10589923020,1d9b5332-5ca6-40be-b408-250606f68c17,2017-03-12 17:00:48,5,,注冊會員,金黑色.,36 10200243913,10589923020,966cda26-ce10-432a-8309-95199ad1903e,2017-03-10 16:15:02,5,,銅牌會員,金黑色.,36 10164313667,10589923020,d09eab89-ed53-47a3-abd1-c897a8bcf694,2017-02-26 20:15:01,5,北京,銅牌會員,金黑色.,36 10162862191,10589923020,ddb58374-f48b-45f9-a2a6-e5e60d53d4ce,2017-02-26 11:42:58,5,,銅牌會員,金黑色.,36 10149921178,11242420873,5f410ce9-fc38-4736-8465-88bbdd7da347,2017-02-21 19:45:56,5,上海,銅牌會員,70060黑色,36 10143787582,11242420873,3f15f14f-1d37-4ccb-befa-9acccd22a3d1,2017-02-19 19:07:20,5,海南,銅牌會員,70060黑色,36 10150729539,11242420873,a601a457-1cef-41c4-955b-3df3dd2646ec,2017-02-22 07:32:52,5,新疆,銅牌會員,70060黑色,36 10147517331,11242420873,b50e1e32-e1fe-4084-b95a-71be8a720950,2017-02-20 23:29:52,5,北京,銅牌會員,70060黑色,36 10147357719,11242420873,fe6ec9de-c39b-4d5e-9cee-bf5926abb465,2017-02-20 22:18:46,5,湖南,銅牌會員,70060黑色,36 10187242860,11242420873,f12f02f7-b378-457f-a501-cdd81f69de6c,2017-03-06 13:53:31,5,云南,銅牌會員,70060黑色,36 10203999129,11242420873,f61e40df-f919-43a2-b876-e81176d59cf9,2017-03-11 20:55:40,5,內蒙古,注冊會員,70060黑色,36 10203827884,11242420873,4a73b3d7-b489-4880-8f8a-bc70015c4e18,2017-03-11 19:55:57,5,浙江,注冊會員,70060黑色,36 10203810598,11242420873,4113c7e0-4556-4aa1-b441-2334bd5419d4,2017-03-11 19:49:51,5,安徽,注冊會員,70060黑色,36 10203802320,11242420873,38a65bba-5284-4190-83f2-1a6a54d57da3,2017-03-11 19:46:57,5,廣西,注冊會員,70060黑色,36
shoe_details.csv
10536835318,她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼,卡曼鞋類專營店,9.72|9.75|9.65|9.63 1587186408,雅詩萊雅休閑鞋女 圓頭深口低幫鞋 拼色厚底女鞋 系帶防水臺女鞋子 GH852Q0紅色 37,宏嘉男鞋專營店,9.79|9.80|9.74|9.76 10536835318,她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼,卡曼鞋類專營店,9.72|9.75|9.65|9.63 11242420873,百芙蓉單鞋女中跟2017春季新款粗跟英倫風小皮鞋女春季新款圓頭深口媽媽工作韓版潮厚底 70060黑色 36,百芙蓉鞋類旗艦店,9.88|9.81|9.83|9.84 11157498264,圓頭深口低幫鞋2017年秋冬新款純色系帶坡跟女鞋防水臺女鞋子 1343黑色 36,馬登爾鞋靴專營店,9.78|9.81|9.75|9.76 10638093860,愛思圖牛津鞋英倫風皮鞋女中跟秋季女鞋粗跟單鞋大頭皮鞋圓頭學生鞋小皮鞋平底鞋潮媽媽鞋女生鞋子 黑色ML6X303 36,愛思圖旗艦店,9.72|9.76|9.71|9.70 10574081025,佩尼泰深口單鞋女頭層牛皮尖頭單鞋中跟粗跟 OL工作職業鞋大小碼女鞋春季新款 灰色 38,佩尼泰旗艦店,9.68|9.73|9.67|9.66 10459020322,瑞蓓妮真皮女鞋2017新款魔術貼深口單鞋女平底舒適休閑鞋大碼防滑中老年媽媽鞋 黑色單鞋 38,瑞蓓妮旗艦店,9.70|9.75|9.65|9.65 11273711543,細跟高跟鞋女2017春季新款尖頭單鞋女深口高跟女士英倫厚底防水臺工作女鞋 紅色 37,家興福鞋業專營店,9.87|9.82|9.80|9.81 11226902308,粗跟單鞋女2017春季新款女鞋OL尖頭高跟鞋深口工作鞋女士皮鞋水鉆百搭鞋子女 DH3658黑色 37,彬度鳥鞋靴旗艦店,9.89|9.83|9.83|9.84 11210447351,她芙 單鞋女2017春季新款單鞋粗跟女鞋子系帶厚底高跟鞋深口學生休閑低幫鞋 綠色 37,她芙旗艦店,9.77|9.77|9.67|9.68 11239261516,AUSDU休閑鞋女圓頭平底深口單鞋粗跟厚底2017春款韓版百搭舒適女鞋媽媽綁帶學生 70030黑色 36,AUSDU鞋類旗艦店,9.87|9.80|9.81|9.82 11267204558,丹芭莎春季女鞋2017新品純色深口鞋女韓版圓頭高跟鞋粗跟防水臺單鞋女潮鞋 M70050黑色 37,丹芭莎旗艦店,9.84|9.81|9.79|9.80 10687936751,fullmir內增高休閑鞋女士小白鞋2016秋季新款厚底鞋韓版潮流低幫學生運動鞋子單鞋 紅 色 37,fullmir鞋類旗艦店,9.61|9.66|9.58|9.58 11167186789,新款單鞋女2017秋季時尚漆皮圓頭低幫休閑鞋秋鞋 工作鞋套腳歐美低跟皮鞋 黑色6119 34,艾琳藝鞋類專營店,9.67|9.79|9.67|9.69 11227438800,意米思時尚女鞋圓頭高跟鞋粗跟媽媽鞋深口單鞋女2017春秋新款韓版百搭小皮鞋防水臺鞋子女 莫70050黑色 36,意米思旗艦店,9.72|9.81|9.79|9.80 11250120847,鄰家天使細跟單鞋2017春季新款尖頭歐美皮鞋深口高跟女鞋春秋款鞋子 LJ619黑色 39標碼,鄰家天使鞋類旗艦店,9.69|9.74|9.65|9.66 11193717829,單鞋女2017春季新款韓版高跟防水臺粗跟女鞋尖頭深口水鉆通勤OL工作小皮鞋女 鄰1231黑色 37,NEB ANGEL梓贏專賣店,9.78|9.78|9.74|9.75 11166169416,金絲兔尖頭單鞋女2017春季新品深口金屬超高跟鞋歐美時尚細跟女鞋百搭小皮鞋工作鞋 黑色 36,金絲兔廣匯達專賣店,9.89|9.83|9.83|9.84 10617152040,ZHR小皮鞋真皮小白鞋女深口單鞋平底護士工作鞋潮 白色 39,零邦鞋靴專營店,9.69|9.68|9.69|9.69 1471841136,寶思特2017春季新款真皮平底平跟休閑女單鞋軟牛皮軟底媽媽鞋花朵跳舞鞋加大碼女鞋子 黑色 39,寶思特旗艦店,9.75|9.74|9.65|9.65 11204372265,霍爾世家 深口單鞋女粗跟高跟鞋2017春季新款英倫風真皮尖頭女鞋防水臺 黑色 37,霍爾世家旗艦店,9.64|9.70|9.63|9.64
至此,我們完成了整個數據的爬取工作。
有經驗的讀者可以看出來,本文完成的爬蟲是較為基礎的爬蟲,不涉及到Scrapy高級的特性,也不涉及到反爬蟲的內容,對于感興趣的讀者,可以從以下幾個方面繼續深入。
由于京東對爬蟲爬取評論并沒有反爬措施,所以本文沒有涉及到反爬的內容,不過在編寫該爬蟲的時候有考慮到這部分內容,所以編寫了中間件來完成User-Agent的隨機設置以及使用代理池來分散請求等簡單的反爬措施,有興趣的讀者可以查閱Github源代碼。
對于較大的爬取工作,可以考慮使用scrapy-redis等工具來構建分布式爬蟲,以增加爬取效率。
在獲得大量的數據之后,可以使用matplotlib等工具對數據進行可視化分析。
以上就是本文的全部內容,有興趣的讀者可以查閱Github并下載源碼,該項目地址: https://github.com/Time1ess/MyCodes/tree/master/scrapy/jd
天想跟大家分享的是關于網絡爬蟲的相關知識,網絡爬蟲是一種根據一定的規則,自動地對互聯網上相關內容進行抓取的程序或者腳本,本文的內容主要是通過分析京東評論的加載過程,獲取相關API,然后通過使用基于Python語言的開源網絡爬蟲框架——Scrapy,大量獲取相關評論內容。
本文假定讀者具有一定的Python編程經驗,具有少量HTTP協議和HTML的相關知識,對爬蟲的工作原理有一定了解。
在開始編寫爬蟲之前,我們需要獲得啟動爬蟲所需要的相關鏈接。在本文,我們將以對京東鞋類評論爬取為例,進行說明(其他種類爬取流程類似,區別只在于數據處理)。
首先打開京東,搜索“鞋”,打開任意一件商品,并切換到“商品評價”標簽頁,如圖所示。
啟用瀏覽器的網頁分析功能,以Safari瀏覽器為例,右鍵點擊網頁任意部分,選擇”檢查元素“,切換到“網絡”標簽下,如果有其他內容的話,可以點擊右側的垃圾桶圖標清空歷史,如圖所示。
然后我們點擊評論區的換頁按鈕,切換到任意一頁新的評論,此時可以發現瀏覽器對本次點擊產生的數據交換過程進行了記錄,我們發現其中有一條名為”productPageComments.action”的記錄,對其進行分析可以看到對應的完整URL,如圖所示。
其完整URL為:https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv6630&productId=10353518575&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0
顯而易見,評論的加載是通過GET請求實現,對我們來說,該URL中最關鍵的GET參數為productID和page,它們分別定義了對應的商品編號以及評論頁碼。通過訪問該URL,我們可以得到內容如圖所示。
可以看到,該URL返回的內容為json數據包,同時以請求中callback定義的函數名對其進行包裹,這一點從整個數據包最前方可以看出。我們將GET請求中callback參數去掉以后即可得到原始的json數據包,如圖所示。
因此,在不考慮其他參數的情況下,我們需要的API格式為:https://club.jd.com/comment/productPageComments.action?productId={}&score=0&sortType=5&page={}&pageSize=10&isShadowSku=0
至此,我們獲得了返回任意商品的任意評論頁的API,下面我們將對API返回數據本身的內容進行分析。
從前面圖中可以看出,API返回數據應該是一個字典,我們通過使用requests獲得API返回字典以及Python的json模塊進行分析。
其中對我們來說最重要的是鍵comments所對應的值,值為一個列表,其中每個元素為一個字典,存放的是每一條評論的相關信息。
根據實際需要,在本次實現中選取了以下信息:
guid –> 評論用戶id
id –> 該評論id
referenceId –> 評論商品id
creationTime –> 評論時間
score –> 評論評分
userProvince –> 評論用戶歸屬地
userLevelName –> 評論用戶會員級別
productColor –> 評論用戶購買顏色
productSize –> 評論用戶購買尺寸
至此,我們完成了對API返回字典的分析,在構建Scrapy爬蟲之前,我們還需要對商品列表進行分析。
我們已經擁有對任意給定的商品id,獲取其所有評論的API,但在構建爬蟲之前,我們還有最后一個問題,如何獲得商品id?
我們可以很容易的獲得并格式化京東的搜索鏈接:https://search.jd.com/Search?keyword={}&enc=utf-8&page={},根據該格式化鏈接,我們只需要填寫搜索關鍵字以及搜索頁碼就能得到對應頁的搜索結果。通過對網頁源代碼進行分析,可以發現每個商品都處于class="gl-item"的li元素下,如圖所示。
我們只需要對class="gl-item"的li元素下class="p-img"的div元素下的a元素的href屬性進行提取處理即可得到商品id,如圖中的10353518575。
至此,我們完成了對商品列表的分析工作,接下來我們將構建基于Scrapy的爬蟲來完成對評論的爬取工作。
我們在上節中獲得了商品的詳細信息鏈接,如:https://item.jd.com/10353518575.html,我們可以對該頁面內容進行爬取以獲得更全面的商品信息。在這部分需要注意的是,很多內容是通過JavaScript進行動態加載的,在爬取時需要注意,否則得到的數據并不符合需要。通過啟用瀏覽器的“停用JavaScript”功能,可以看到在不執行JavaScript時的頁面是什么樣的,如圖所示。
可以看到,商品的價格等信息是沒有進行加載的,所以如果需要對價格進行爬取,需要使用到selenium等工具來完成瀏覽器的模擬或者進一步分析JavaScript的執行邏輯。
Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。其最初是為了網絡抓取所設計的,也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。
要使用Scrapy,首先得建立項目:
$ scrapy startproject jd New Scrapy project 'jd', using template directory '/usr/local/lib/python3.6/site-packages/scrapy/templates/project', created in: /private/tmp/jd You can start your first spider with: cd jd scrapy genspider example example.com
在建好的jd文件夾下,有一個jd文件夾以及一個scrapy.cfg文件,進入前者,可以看到以下內容:
$ ls __init__.py items.py pipelines.py spiders __pycache__ middlewares.py settings.py
其中:
items.py –> 完成數據容器Item的定義
爬取的主要目標就是從非結構性的數據源提取結構性數據,例如網頁。Scrapy提供 Item 類來滿足這樣的需求。Item 對象是種簡單的容器,保存了爬取到得數據。 其提供了 類似于詞典(dictionary-like) 的API以及用于聲明可用字段的簡單語法。
pipelines.py –> 完成對Item處理流水線的定義
當Item在Spider中被收集之后,它將會被傳遞到Item Pipeline,一些組件會按照一定的順序執行對Item的處理。每個item pipeline組件(有時稱之為“Item Pipeline”)是實現了簡單方法的Python類。他們接收到Item并通過它執行一些行為,同時也決定此Item是否繼續通過pipeline,或是被丟棄而不再進行處理。
以下是item pipeline的一些典型應用:
清理HTML數據
驗證爬取的數據(檢查item包含某些字段)
查重(并丟棄)
將爬取結果保存到數據庫中
middlewares.py –> 完成Spider中間件的定義
Spider中間件是介入到Scrapy的spider處理機制的鉤子框架,通過定義并使用中間件,可以對發送給Spiders的response以及Spiders產生的Request對象進行處理。
settings.py –> 完成對爬蟲的控制
Scrapy settings提供了定制Scrapy組件的方法。通過修改settings.py,可以控制包括核心(core),插件(extension),pipeline及spider組件。settings為代碼提供了提取以key-value映射的配置值的的全局命名空間(namespace)。settings同時也是選擇當前激活的Scrapy項目的方法。
spiders –> 完成對爬蟲Spider的定義
Spider類定義了如何爬取某個(或某些)網站。包括了爬取的動作(例如:是否跟進鏈接)以及如何從網頁的內容中提取結構化數據(爬取item)。換句話說,Spider就是定義爬取的動作及分析某個網頁(或者是有些網頁)的地方。
定義數據容器items
定義爬蟲類
創建爬蟲類的命令為:
scrapy genspider [爬蟲名] [允許爬取域名]
$ scrapy genspider shoes jd.com Created spider 'shoes' using template 'basic' in module: jd.spiders.shoes
接著打開spiders文件夾下的shoes.py文件進行編輯:
首先我們需要定義一些變量,比如包含搜索關鍵字的列表、格式化搜索鏈接、格式化評論API鏈接等:
然后編輯ShoesSpider類:
詳細分析下這段代碼:
類ShoesSpider繼承自Spider,其余可繼承的類還有CrawlSpider、XMLFeedSpider、SitemapSpider,在這里我們使用了最基本的Spider。
屬性name定義了該爬蟲的名字,在啟動爬蟲的步驟中需要提供爬蟲名字。
屬性allowed_domains定義了一個列表,可以包含一個或多個域名,爬蟲只會對該域名下的鏈接進行爬取。
屬性start_urls定義了一個列表,spider啟動時將從中獲取鏈接進行爬取。
實例方法parse定義了對商品列表頁面進行處理的相關邏輯:
接收一個response參數,該response對象為爬蟲根據Request對象請求獲得的結果。
根據前面幾節的描述,parse方法針對商品列表頁面使用xpath進行分析。
在提取到商品iid后,對該頁面下所有商品iid進行遍歷,分別為商品詳細頁面(可選)以及商品評論頁面構建Request請求,注意使用了yield,因為我們需要返回多個請求而不是一個請求。
對每個Request請求,我們指定了相關參數,比如鏈接、回調函數,以及通過meta關鍵字保存上下文信息字典,這可以在回調函數中訪問Response的meta屬性獲得。
實例方法parse_detail定義了對商品詳細頁面進行處理的相關邏輯:
我們依然通過xpath進行分析,獲得了商品名、商家名、商家評分等信息,使用其實例化ShoeDetailItem類并返回該實例。
實例方法parse_comment定義了對商品評論進行處理的相關邏輯:
根據在Request對象中設置meta屬性,我們可以很方便地獲得當前物品id、當前評論頁碼、以及訪問重試次數。
我們需要對response對象的text屬性使用json.loads進行格式化,但是由于各種原因可能會失敗,所以我們設置了方式重試次數這一變量來控制重試,當本次json.loads格式化失敗,我們會再次進行嘗試訪問該評論鏈接,直到達到最大重試次數10次,然后放棄。
如果解析成功,判斷解析后的字典中鍵comments所對應的內容是否為空,為空代表已經沒有更多評論,則返回。
否則,對每條評論進行遍歷,使用其中的參數實例化ShoeCommentItem類并返回該實例。
在結束評論遍歷后,嘗試對評論下一頁發出Request請求。
至此,我們完成了爬蟲的工作邏輯,接下來需要對流水線進行定義,完成數據的查重以及保存等操作。
定義pipeline流水線
對于各個parse方法返回的Item對象,它們將會被傳遞到在pipelines.py中定義以及settings.py中啟用的流水線中進行處理。
在本文中我們需要對每個Item對象做兩件事,去重以及保存。對于ShoeCommentItem的流水線定義如下:
需要解釋的是類方法from_crawler和實例方法process_item,前者在初始化時會被調用,后者在出現Item
對象時被調用。
對于from_crawler方法:
我們需要忽略之前已經處理過的評論,因此采用了一個set來存儲已經處理過的id
在初始化時,打開之前保存的評論文件shoe_comments.csv,從中獲取id并對seen_ids進行填充
這是一個類方法,需要在最后返回類的實例
對于process_item方法:
方法接收兩個參數,前一個是返回的Item對象,后一個是返回該對象的對應Spider對象
首先判斷了該Item是否是類ShoeCommentItem實例,如果不是的話不進行處理直接返回該對象
提取該對象的id并判斷該對象是否已經處理過,已經處理過的話拋出DropItem異常,停止后續流水線的處理
將該對象id加入seen_ids,并根據val_indices定義的順序將其排序及格式化字符串并追加到shoe_comments.csv中
返回該對象
需要特別注意的是,process_item方法必須返回一個Item(或任何繼承類)對象或者是拋出DropItem
異常,被丟棄的item將不會被之后的pipeline組件所處理,而正常返回的會。
同理我們可以定義ShoeDetailItem的流水線:
該流水線邏輯與前一個類似,在此不再贅述。
settings.py的配置
我們還需要對settings.py進行配置。
其中關鍵的幾個設置是:
CONCURRENT_REQUESTS(并發請求數): 100
COOKIES_ENABLED(啟用cookies): False
ITEM_PIPELINES(item流水線): {‘jd.pipelines.ShoeCommentPipeline’: 300, ‘jd.pipelines.ShoeDetailPipeline’: 301}
具體設置可以根據自己的需求進行設置,以上只是一個示例。
啟動
最后,讓我們啟動這個爬蟲:
$ scrapy crawl shoes
可以在控制臺看到輸出:
2017-03-13 19:21:12 [scrapy.utils.log] INFO: Scrapy 1.3.0 started (bot: jd) 2017-03-13 19:21:12 [scrapy.utils.log] INFO: Overridden settings: {'BOT_NAME': 'jd', 'CONCURRENT_REQUESTS': 100, 'COOKIES_ENABLED': False, 'DOWNLOAD_DELAY': 0.01, 'NEWSPIDER_MODULE': 'jd.spiders', 'SPIDER_MODULES': ['jd.spiders']} 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.logstats.LogStats'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'jd.middlewares.RandomUserAgentMiddleware', 'jd.middlewares.ProxyMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2017-03-13 19:21:12 [scrapy.middleware] INFO: Enabled item pipelines: ['jd.pipelines.ShoeCommentPipeline', 'jd.pipelines.ShoeDetailPipeline'] 2017-03-13 19:21:12 [scrapy.core.engine] INFO: Spider opened 2017-03-13 19:21:12 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-03-13 19:21:12 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023 2017-03-13 19:21:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=3> (referer: None) 2017-03-13 19:21:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=7> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=6> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=9> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=5> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=10> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=2> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=1> (referer: None) 2017-03-13 19:21:16 [scrapy.dupefilters] DEBUG: Filtered duplicate request: <GET http://item.jd.com/10536835318.html> - no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=8> (referer: None) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://item.jd.com/10536835318.html> (referer: https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=6) 2017-03-13 19:21:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> (referer: https://search.jd.com/Search?keyword=%E5%A5%B3%E6%B7%B1%E5%8F%A3%E5%8D%95%E9%9E%8B&enc=utf-8&page=7) 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 http://item.jd.com/10536835318.html> {'iid': 10536835318, 'name': '她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼', 'scores': '9.72|9.75|9.65|9.63', 'shop': '卡曼鞋類專營店'} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10199823376, 'color': '金黑色.', 'creation_time': '2017-03-10 13:59:31', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '069d0baa-022b-421b-a43a-584f5aa3921e', 'user_level': '銅牌會員', 'user_province': ''} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10175008135, 'color': '金黑色.', 'creation_time': '2017-03-02 12:18:57', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '28dfd6c2-caf2-427d-9927-cf088d3099ea', 'user_level': '銅牌會員', 'user_province': '湖南'} 2017-03-13 19:21:16 [scrapy.core.scraper] DEBUG: Scraped from <200 https://club.jd.com/comment/productPageComments.action?productId=10589923020&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0> {'_id': 10163486837, 'color': '金黑色.', 'creation_time': '2017-02-26 15:28:14', 'iid': '10589923020', 'score': 5, 'size': '36', 'uid': '736ad5a4-9470-4dcc-832d-b59094cf84f4', 'user_level': '銅牌會員', 'user_province': '云南'}
在運行一段時間后,查看shoe_comments.csv和shoe_details.csv內容:
shoe_comments.csv
10199823376,10589923020,069d0baa-022b-421b-a43a-584f5aa3921e,2017-03-10 13:59:31,5,,銅牌會員,金黑色.,36 10175008135,10589923020,28dfd6c2-caf2-427d-9927-cf088d3099ea,2017-03-02 12:18:57,5,湖南,銅牌會員,金黑色.,36 10163486837,10589923020,736ad5a4-9470-4dcc-832d-b59094cf84f4,2017-02-26 15:28:14,5,云南,銅牌會員,金黑色.,36 10205838152,10589923020,93f35818-129f-4aaa-8ea9-549c28a4f791,2017-03-12 14:37:59,5,,注冊會員,金黑色.,36 10175298549,10589923020,fe1a26e0-8cae-43c3-b0d4-c99bf1d961cf,2017-03-02 13:49:07,5,,銅牌會員,金黑色.,36 10205858068,10589923020,65a7243e-7116-4075-b64a-6e8d8d8382a4,2017-03-12 14:44:29,5,,銅牌會員,金黑色.,36 10206280836,10589923020,1d9b5332-5ca6-40be-b408-250606f68c17,2017-03-12 17:00:48,5,,注冊會員,金黑色.,36 10200243913,10589923020,966cda26-ce10-432a-8309-95199ad1903e,2017-03-10 16:15:02,5,,銅牌會員,金黑色.,36 10164313667,10589923020,d09eab89-ed53-47a3-abd1-c897a8bcf694,2017-02-26 20:15:01,5,北京,銅牌會員,金黑色.,36 10162862191,10589923020,ddb58374-f48b-45f9-a2a6-e5e60d53d4ce,2017-02-26 11:42:58,5,,銅牌會員,金黑色.,36 10149921178,11242420873,5f410ce9-fc38-4736-8465-88bbdd7da347,2017-02-21 19:45:56,5,上海,銅牌會員,70060黑色,36 10143787582,11242420873,3f15f14f-1d37-4ccb-befa-9acccd22a3d1,2017-02-19 19:07:20,5,海南,銅牌會員,70060黑色,36 10150729539,11242420873,a601a457-1cef-41c4-955b-3df3dd2646ec,2017-02-22 07:32:52,5,新疆,銅牌會員,70060黑色,36 10147517331,11242420873,b50e1e32-e1fe-4084-b95a-71be8a720950,2017-02-20 23:29:52,5,北京,銅牌會員,70060黑色,36 10147357719,11242420873,fe6ec9de-c39b-4d5e-9cee-bf5926abb465,2017-02-20 22:18:46,5,湖南,銅牌會員,70060黑色,36 10187242860,11242420873,f12f02f7-b378-457f-a501-cdd81f69de6c,2017-03-06 13:53:31,5,云南,銅牌會員,70060黑色,36 10203999129,11242420873,f61e40df-f919-43a2-b876-e81176d59cf9,2017-03-11 20:55:40,5,內蒙古,注冊會員,70060黑色,36 10203827884,11242420873,4a73b3d7-b489-4880-8f8a-bc70015c4e18,2017-03-11 19:55:57,5,浙江,注冊會員,70060黑色,36 10203810598,11242420873,4113c7e0-4556-4aa1-b441-2334bd5419d4,2017-03-11 19:49:51,5,安徽,注冊會員,70060黑色,36 10203802320,11242420873,38a65bba-5284-4190-83f2-1a6a54d57da3,2017-03-11 19:46:57,5,廣西,注冊會員,70060黑色,36
shoe_details.csv
10536835318,她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼,卡曼鞋類專營店,9.72|9.75|9.65|9.63 1587186408,雅詩萊雅休閑鞋女 圓頭深口低幫鞋 拼色厚底女鞋 系帶防水臺女鞋子 GH852Q0紅色 37,宏嘉男鞋專營店,9.79|9.80|9.74|9.76 10536835318,她芙 單鞋女2017春季新款中跟短靴女時尚女鞋性感尖頭細跟單鞋深口裸靴防水臺高跟鞋 黑色 37-標準碼,卡曼鞋類專營店,9.72|9.75|9.65|9.63 11242420873,百芙蓉單鞋女中跟2017春季新款粗跟英倫風小皮鞋女春季新款圓頭深口媽媽工作韓版潮厚底 70060黑色 36,百芙蓉鞋類旗艦店,9.88|9.81|9.83|9.84 11157498264,圓頭深口低幫鞋2017年秋冬新款純色系帶坡跟女鞋防水臺女鞋子 1343黑色 36,馬登爾鞋靴專營店,9.78|9.81|9.75|9.76 10638093860,愛思圖牛津鞋英倫風皮鞋女中跟秋季女鞋粗跟單鞋大頭皮鞋圓頭學生鞋小皮鞋平底鞋潮媽媽鞋女生鞋子 黑色ML6X303 36,愛思圖旗艦店,9.72|9.76|9.71|9.70 10574081025,佩尼泰深口單鞋女頭層牛皮尖頭單鞋中跟粗跟 OL工作職業鞋大小碼女鞋春季新款 灰色 38,佩尼泰旗艦店,9.68|9.73|9.67|9.66 10459020322,瑞蓓妮真皮女鞋2017新款魔術貼深口單鞋女平底舒適休閑鞋大碼防滑中老年媽媽鞋 黑色單鞋 38,瑞蓓妮旗艦店,9.70|9.75|9.65|9.65 11273711543,細跟高跟鞋女2017春季新款尖頭單鞋女深口高跟女士英倫厚底防水臺工作女鞋 紅色 37,家興福鞋業專營店,9.87|9.82|9.80|9.81 11226902308,粗跟單鞋女2017春季新款女鞋OL尖頭高跟鞋深口工作鞋女士皮鞋水鉆百搭鞋子女 DH3658黑色 37,彬度鳥鞋靴旗艦店,9.89|9.83|9.83|9.84 11210447351,她芙 單鞋女2017春季新款單鞋粗跟女鞋子系帶厚底高跟鞋深口學生休閑低幫鞋 綠色 37,她芙旗艦店,9.77|9.77|9.67|9.68 11239261516,AUSDU休閑鞋女圓頭平底深口單鞋粗跟厚底2017春款韓版百搭舒適女鞋媽媽綁帶學生 70030黑色 36,AUSDU鞋類旗艦店,9.87|9.80|9.81|9.82 11267204558,丹芭莎春季女鞋2017新品純色深口鞋女韓版圓頭高跟鞋粗跟防水臺單鞋女潮鞋 M70050黑色 37,丹芭莎旗艦店,9.84|9.81|9.79|9.80 10687936751,fullmir內增高休閑鞋女士小白鞋2016秋季新款厚底鞋韓版潮流低幫學生運動鞋子單鞋 紅 色 37,fullmir鞋類旗艦店,9.61|9.66|9.58|9.58 11167186789,新款單鞋女2017秋季時尚漆皮圓頭低幫休閑鞋秋鞋 工作鞋套腳歐美低跟皮鞋 黑色6119 34,艾琳藝鞋類專營店,9.67|9.79|9.67|9.69 11227438800,意米思時尚女鞋圓頭高跟鞋粗跟媽媽鞋深口單鞋女2017春秋新款韓版百搭小皮鞋防水臺鞋子女 莫70050黑色 36,意米思旗艦店,9.72|9.81|9.79|9.80 11250120847,鄰家天使細跟單鞋2017春季新款尖頭歐美皮鞋深口高跟女鞋春秋款鞋子 LJ619黑色 39標碼,鄰家天使鞋類旗艦店,9.69|9.74|9.65|9.66 11193717829,單鞋女2017春季新款韓版高跟防水臺粗跟女鞋尖頭深口水鉆通勤OL工作小皮鞋女 鄰1231黑色 37,NEB ANGEL梓贏專賣店,9.78|9.78|9.74|9.75 11166169416,金絲兔尖頭單鞋女2017春季新品深口金屬超高跟鞋歐美時尚細跟女鞋百搭小皮鞋工作鞋 黑色 36,金絲兔廣匯達專賣店,9.89|9.83|9.83|9.84 10617152040,ZHR小皮鞋真皮小白鞋女深口單鞋平底護士工作鞋潮 白色 39,零邦鞋靴專營店,9.69|9.68|9.69|9.69 1471841136,寶思特2017春季新款真皮平底平跟休閑女單鞋軟牛皮軟底媽媽鞋花朵跳舞鞋加大碼女鞋子 黑色 39,寶思特旗艦店,9.75|9.74|9.65|9.65 11204372265,霍爾世家 深口單鞋女粗跟高跟鞋2017春季新款英倫風真皮尖頭女鞋防水臺 黑色 37,霍爾世家旗艦店,9.64|9.70|9.63|9.64
至此,我們完成了整個數據的爬取工作。
有經驗的讀者可以看出來,本文完成的爬蟲是較為基礎的爬蟲,不涉及到Scrapy高級的特性,也不涉及到反爬蟲的內容,對于感興趣的讀者,可以從以下幾個方面繼續深入。
由于京東對爬蟲爬取評論并沒有反爬措施,所以本文沒有涉及到反爬的內容,不過在編寫該爬蟲的時候有考慮到這部分內容,所以編寫了中間件來完成User-Agent的隨機設置以及使用代理池來分散請求等簡單的反爬措施,有興趣的讀者可以查閱Github源代碼。
對于較大的爬取工作,可以考慮使用scrapy-redis等工具來構建分布式爬蟲,以增加爬取效率。
在獲得大量的數據之后,可以使用matplotlib等工具對數據進行可視化分析。
以上就是本文的全部內容,有興趣的讀者可以查閱Github并下載源碼,該項目地址: https://github.com/Time1ess/MyCodes/tree/master/scrapy/jd
*請認真填寫需求信息,我們會在24小時內與您取得聯系。