Scrapy項目搭建的完整步驟

Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。其最初是爲了頁面抓取 (更確切來說, 網絡抓取 )所設計的, 也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試。

(一)scrapy整體架構圖

在這裏插入圖片描述

(二)Scrapy主要組件

  • 1、引擎(Scrapy): 用來處理整個系統的數據流處理, 觸發事務(框架核心)。
  • 2、調度器(Scheduler): 用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址。
  • 3、下載器(Downloader): 用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的異步模型上的)。
  • 4、爬蟲(Spiders): 爬蟲是主要幹活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面。
  • 5、項目管道(Pipeline): 負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並經過幾個特定的次序處理數據。
  • 6、下載器中間件(Downloader Middlewares): 位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
  • 7、爬蟲中間件(Spider Middlewares): 介於Scrapy引擎和爬蟲之間的框架,主要工作是處理蜘蛛的響應輸入和請求輸出。
  • 8、調度中間件(Scheduler Middewares): 介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。
scrapy startproject yaowang    #創建項目

在這裏插入圖片描述
下面來簡單介紹一下各個主要文件的作用:

scrapy.cfg:項目的配置文件
yaowang/:項目的Python模塊,將會從這裏引用代碼
yaowang/items.py:項目的字段定義文件
yaowang/pipelines.py:項目的管道文件
yaowang/settings.py:項目的設置文件
yaowang/spiders/:存儲爬蟲代碼目錄

(三)定義存儲對象(yaowangl/items.py)
Items是裝載我們抓取數據的容器。它們工作像簡單的Python字典,它提供更多的保護,比如對未定義的字段提供填充功能防止出錯.
Itmes.py
在這裏插入圖片描述

(四)製作爬蟲 (yaowang/spiders/)

1、在當前目錄下輸入命令,將在yaowang/spider目錄下創建一個名爲的爬蟲,並指定爬取域的範圍:

scrapy genspider yao 111.com.cn   #創建爬蟲

2、打開 tutorial/spider目錄裏的 hsw.py,默認增加了下列代碼:
yao.py

# -*- coding: utf-8 -*-
import scrapy
from lxml import etree
from yaowang.items import YaowangItem

class YaoSpider(scrapy.Spider):
    name = 'yao'
    allowed_domains = ['111.com.cn']
    start_urls = []

    for i in range(1,51):
        url = f'https://www.111.com.cn/categories/953710-j{i}.html'
        start_urls.append(url)

    def parse(self, response):
        # with open('yaowang.html','w',encoding='utf-8')as fp:
        #     fp.write(response.body.decode('gbk'))
        # 提取HTML頁面
        tree = etree.HTML(response.body.decode('gbk'))
        # 所有藥品的盒子
        li_list = tree.xpath('//ul[@id="itemSearchList"]/li')
        # print(len(li_list))
        for li in li_list:
            # 實例化item
            item = YaowangItem()

            # 藥名
            name = li.xpath('./div[1]/p[@class="titleBox"]/a/text()')
            name = [i.strip() for i in name]
            name = ''.join(name).strip()
            # print(name)

            # 圖片鏈接
            href = li.xpath('./div[1]/a//img/@src')[0]
            # print(href)

            # 價格
            price = li.xpath('./div[1]/p[@class="price"]//span/text()')[0]
            price = price.strip()
            # print(price)

            # 藥店
            store = li.xpath('./div[1]/div[@class="sell_type_div"]/span[2]//text()')[0]
            # print(store)

            # 詳情url
            url = li.xpath('./div[1]/a/@href')[0]
            full_url = "https:" + url
            # print(full_url)

            item['name'] = name
            item['href'] = href
            item['price'] = price
            item['store'] = store
            item['url'] = full_url
            # 默認過濾相同的url請求
            yield scrapy.Request(url=full_url,callback=self.parse_detail,meta={'data':item})
            # yield item

    # 二級頁面,詳情頁數據提取
    def parse_detail(self,response):
        # 繼承上一頁頁面的item數據
        item = response.meta['data']
        # with open('yaowang_detail.html','w',encoding='utf-8')as fp:
        #     fp.write(response.body.decode('gbk'))
        tree = etree.HTML(response.body.decode('gbk'))
        # 商品詳情信息
        # div = tree.xpath('//div[@class="goods_intro"]/table')
        # 商品名稱
        shop_name = tree.xpath('//div[@class="goods_intro"]//tr[1]/td/text()')[0]
        print("========",shop_name)
        # 品牌
        brand = tree.xpath('//div[@class="goods_intro"]//tr[2]/td[1]/text()')[0]
        # print("========", brand)
        # 規格
        standard = tree.xpath('//div[@class="goods_intro"]//tr[2]/td[2]/text()')[0]
        # print("========", standard)
        # 重量
        weight = tree.xpath('//div[@class="goods_intro"]//tr[3]/td[1]/text()')[0]
        # print("========", weight)
        # 生產廠商
        produce = tree.xpath('//div[@class="goods_intro"]//tr[3]/td[2]/text()')[0]
        # print("========", produce)
        # 批准文號
        approval_num = tree.xpath('//div[@class="goods_intro"]//tr[4]/td[1]//text()')
        approval_num = [i.strip() for i in approval_num]
        approval_num = ''.join(approval_num)
        # print("========", approval_num)
        # 產品類型
        produce_type = tree.xpath('//div[@class="goods_intro"]//tr[4]/td[2]/text()')[0]
        produce_type = produce_type.strip()
        # print("========", produce_type)

        # item存儲數據
        item['shop_name'] = shop_name
        item['brand'] = brand
        item['standard'] = standard
        item['weight'] = weight
        item['produce'] = produce
        item['approval_num'] = approval_num
        item['produce_type'] = produce_type

        yield item

3、要建立一個Spider, 你必須用scrapy.Spider類創建一個子類,並確定了三個強制的屬性 和 一個方法。

  • ① name ="":這個爬蟲的識別名稱,必須是唯一的,在不同的爬蟲必須定義不同的名字。
  • ②allow_domains=[]是搜索的域名範圍,也就是爬蟲的約束區域,規定爬蟲只爬取這個域名下的網頁,不存在的URL會被忽略。
  • ③ start_urls=():爬取的URL元祖/列表。爬蟲從這裏開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。
  • ④ parse(self,response):解析的方法,每個初始URL完成下載後將被調用,調用的時候傳入從每一個URL傳回的Response對象來作爲唯一參數,主要作用如下:
    負責解析返回的網頁數據(response.body),提取結構化數據(生成item) b) 生成需要下一頁的URL請求。

4、修改parse方法,添加parse_item方法
現在我們修改yao.py文件將start_urls的值修改爲需要爬取的初始url

start_urls = []
for i in range(1,51):
    url = f'https://www.111.com.cn/categories/953710-j{i}.html'
    start_urls.append(url)

這裏不使用response自帶的xpath,使用lxml xpath
from lxml import etree

在這裏插入圖片描述

5、然後運行一下看看,在yaowang目錄下執行:

scrapy crawl yao -o yao.csv
scrapy保存信息的最簡單的方法主要有四種,-o 輸出指定格式的文件,命令如下:
json格式,默認爲Unicode編碼
scrapy crawl yao -o yao.json
json lines格式,默認爲Unicode編碼
scrapy crawl yao -o yao.jsonl
csv 逗號表達式,可用Excel打開
scrapy crawl yao -o yao.csv
xml格式
scrapy crawl yao -o yao.xml


輸出日誌到指定文件,但是日誌就不會輸出到屏幕上了
scrapy crawl yao -s LOG_FILE=yao.log

6、利用pipelines.py:項目的管道文件進行數據的保存
mysql保存::

class YaowangPipeline(object):
    def __init__(self):
        # 建立數據庫連接
        self.con = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='q1q1q1',
            database='aabbcc',
            charset='utf8')
        # 創建操作遊標
        self.cursor = self.con.cursor()

    def process_item(self, item, spider):
        print("="*30)
        # data_list.append(dict(item))
        # with open('yaowang.json','w',encoding='utf-8')as fp:
        #     json.dump(data_list,fp,ensure_ascii=False)

        name = item['name']
        href = item['href']
        price = item['price']
        store = item['store']
        url = item['url']
        shop_name = item['shop_name']
        brand = item['brand']
        standard = item['standard']
        weight = item['weight']
        produce = item['produce']
        approval_num = item['approval_num']
        produce_type = item['produce_type']
        # 定義sql語句
        # sql = "INSERT INTO yaowang_er(name,href,price,store,url,shop_name,brand,standard,weight,produce,approval_num,produce_type) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
        #
        # # 執行sql語句
        # self.cursor.execute(sql,(name,href,price,store,url,shop_name,brand,standard,weight,produce,approval_num,produce_type))
        # # 保存修改
        # self.con.commit()

        return item
    def __del__(self):
	     # 關閉操作遊標
	     self.cursor.close()
	     # 關閉數據庫連接
	     self.con.close()  

MongoDB保存:

class YaowangMongoPipeline(object):
    def __init__(self):
        # 創建客戶端
        self.client = pymongo.MongoClient('localhost')
        # 創建數據庫
        self.db = self.client['yaowang']
        # 創建集合
        self.collection = self.db['yao_info']
    def process_item(self, item, spider):
        print("="*30)
        self.collection.insert(dict(item))
        return item

然後settings.py 中使用管道文件配置,進行數據保存

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   # 'taoche.pipelines.TaochePipeline': 300,
   'taoche.pipelines.TaocheMongoPipeline': 300,
}

運行爬蟲:

scrapy crawl yao

在這裏插入圖片描述

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