爬取友商產品信息

歡迎關注我的公衆號「測試遊記」

由於想要了解一下友商的產品信息,所以簡單的寫一下爬取他們信息的爬蟲

創建項目

$ scrapy startproject Dahua	
$ cd Dahua	
$ scrapy genspider dahua dahuatech.com
  1. 使用 scrapy腳手架創建一個項目

  2. 進入項目路徑

  3. 創建一個名叫 dahua的爬蟲,它的爬取範圍是 dahuatech.com域名下

分析爬取內容

產品類別url地址爲:http://www.dahuatech.com/product.html

所以修改開始的url start_urls

class DahuaSpider(scrapy.Spider):	
    name = 'dahua'  # 爬蟲名稱	
    allowed_domains = ['dahuatech.com']  # 允許爬取域名	
    start_urls = ['https://www.dahuatech.com/product.html']  # 請求的第一個url	
    def parse(self, response):	
        pass

需要爬取的爲設備的具體信息

640?wx_fmt=jpeg

  • 產品詳情地址

  • 產品名稱

  • 產品描述

  • 產品概述

  • 技術參數

  • 尺寸圖

  • 訂貨型號

所以先在 Dahua/items.py寫上

import scrapy	
class DahuaItem(scrapy.Item):	
    url = scrapy.Field()  # 產品詳情地址	
    product_name = scrapy.Field()  # 產品名稱	
    product_description = scrapy.Field()  # 產品描述	
    product_overview = scrapy.Field()  # 產品概述	
    technical_parameter = scrapy.Field()  # 技術參數	
    dimension_drawing = scrapy.Field()  # 尺寸圖	
    order_type = scrapy.Field()  # 訂貨型號

獲取設備類型列表

從第一個頁面可以看出,設備分成了很多大類,大類中又有很多的小類

640?wx_fmt=jpeg

所以我們先拿到全部小類的url地址

使用 XPathHelper工具進行 Xpath定位

640?wx_fmt=jpeg

由於我懶得解析太多Xpath,所以我取用了離要獲取的url最大層級的 div標籤

對應的URL的Xpath爲://div[@class='product-channel-list f-cb']//a/@href

對呀的文字的Xpath爲://div[@class='product-channel-list f-cb']//a/text()

640?wx_fmt=jpeg

所以爬蟲中第一個解析函數 parse

def parse(self, response):	
    print('正在爬取全部產品類別')	
    url_list = response.xpath("//div[@class='product-channel-list f-cb']//a/@href").extract()	
    productlist_list = response.xpath("//div[@class='product-channel-list f-cb']//a/text()").extract()	
    productlist_list = productlist_list	
    for url, productlist in zip(url_list, productlist_list):	
        if url.startswith('http'):	
            yield scrapy.Request(url=url, callback=self.parse_productlist, meta={'productlist': productlist})

獲取設備列表

任意點擊一個小類進入如下頁面

640?wx_fmt=jpeg

包含了 設備名稱, 描述信息

查看詳情按鈕是進入設備詳情頁的

所以這兒需要獲取到3個Xpath

全部的 查看詳情: //li//span[1]//a/@href

全部的 設備名稱: //div[@class='product-list-b']//ul[@class='f-cb']//h3/text()

全部的 描述信息: //div[@class='product-list-b']//ul[@class='f-cb']//a/p[1]/text()

所以代碼爲:

def parse_productlist(self, response):	
    print('正在爬取產品列表')	
    url_list = response.xpath('//li//span[1]//a/@href').extract()	
    product_name_list = response.xpath("//div[@class='product-list-b']//ul[@class='f-cb']//h3/text()").extract()	
    product_description_list = response.xpath(	
        "//div[@class='product-list-b']//ul[@class='f-cb']//a/p[1]/text()").extract()	
    for url, product_name, product_description in zip(url_list, product_name_list, product_description_list):	
        yield scrapy.Request(url=url, callback=self.parse_productdetail,	
                             meta={	
                                 'productlist': response.meta['productlist'],	
                                 'product_name': product_name,	
                                 'product_description': product_description	
                             })	
    page_list = response.xpath("//div[@class='news-page w1400']//a/@href").extract()	
    page_list = [i for i in page_list if i.startswith('http')]	
    if page_list:	
        for url in page_list:	
            yield scrapy.Request(url=url, callback=self.parse_productlist,	
                                 meta={'productlist': response.meta['productlist']})

往處理詳情頁的地方傳入了 product_nameproduct_description

也就是設備名稱,設備描述

由於部分頁面有多頁,所以也做了頁面的跳轉

page_list = response.xpath("//div[@class='news-page w1400']//a/@href").extract()	
page_list = [i for i in page_list if i.startswith('http')]	
if page_list:	
    for url in page_list:	
        yield scrapy.Request(url=url, callback=self.parse_productlist,	
                             meta={'productlist': response.meta['productlist']})

本來這裏要處理重複頁面的,但是由於 Scrapy自帶了緩存機制,它會跳過爬取相同的 url,所以就這樣了~

獲取詳情頁

640?wx_fmt=jpeg

進入詳情頁後發現數據是動態出現的,使用抓包的方式很容易可以發現它應該ajax請求的方式刷新數據

當前頁面:https://www.dahuatech.com/product/info/93.html

ajax請求頁面:https://www.dahuatech.com/ajax/product/93/1

其中相同的部分爲 93

由於我懶得再爬一層,所以直接用 requests發起了 get請求

def parse_productdetail(self, response):	
    print('正在爬取產品詳情')	
    base_url = 'https://www.dahuatech.com/ajax/product/%s/%s'	
    item = DahuaItem()	
    product_num = re.findall(r'http.*?info/(\d+).html.*?', response.url)	
    product_num = product_num and int(product_num[0])	
    # 產品詳情地址	
    item['url'] = response.url	
    # 產品名稱	
    item['product_name'] = response.meta['product_name']	
    # 產品描述	
    item['product_description'] = response.meta['product_description']	
    # 產品概述	
    item['product_overview'] = re.findall(r'<div class="one_content">(.*?)</div>',	
                                          requests.get(base_url % (product_num, 1)).text,	
                                          re.S | re.M)[0]	
    # 技術參數	
    item['technical_parameter'] = requests.get(base_url % (product_num, 2)).text	
    # 尺寸圖	
    item['dimension_drawing'] = re.findall(r'src=".*?"',	
                                           requests.get(base_url % (product_num, 3)).text,	
                                           re.S | re.M)[0]	
    # 訂貨型號	
    item['order_type'] = re.findall(r'>(.*?)</p',	
                                    requests.get(base_url % (product_num, 4)).text,	
                                    re.S | re.M)[0]	
    yield item

數據持久化

使用最簡單的數據持久化方式:寫入json

修改 Dahua/pipelines.py

import json	
class DahuaPipeline(object):	
    def open_spider(self, spider):	
        self.file = open('dahua.json', 'w')	
    def process_item(self, item, spider):	
        content = json.dumps(dict(item), ensure_ascii=False) + '\n'	
        self.file.write(content)	
        return item	
    def close_spider(self, spider):	
        self.file.close()

一次爬取分爲三步:

  1. 打開 dahua.json文件

  2. 寫入內容

  3. 關閉 dahua.json文件

修改 Dahua/settings.py

  1. 關閉君子協議

ROBOTSTXT_OBEY = False
  1. 開啓數據持久化部分

ITEM_PIPELINES = {	
   'Dahua.pipelines.DahuaPipeline': 300,	
}

查看結果

在外部使用

$ scrapy crawl dahua

640?wx_fmt=jpeg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章