python scrapy爬蟲學習(包含集成django方法,以及在django頁面中啓動爬蟲)

爬蟲開發步驟

一、環境介紹

開發工具:pycharm(社區版本)
python版本:3.7.4
scrapy版本:1.7.3

二、整體步驟

1.創建項目:scrapy startproject xxx(項目名字,不區分大小寫)
2.明確目標 (編寫items.py):明確你想要抓取的目標
3.製作爬蟲 (spiders/xxspider.py):製作爬蟲開始爬取網頁
4.存儲內容 (pipelines.py):設計管道存儲爬取內容
5.設置settings.py:

  1. USER_AGENT=網頁中-F12-網絡-找到爬取地址的請求-右側看消息頭-找到USER_AGENT填寫到該處;
  2. ROBOTSTXT_OBEY=False忽略被爬取網站的允許爬取列表限制,Ture根據授權列表爬取,沒有權限的不去爬取
  3. DOWNLOAD_DELAY=下載延遲,數值
  4. ITEM_PIPELINES=多個管道處理時設置優先級,根據:xx冒號後面的數值大小排序

6.啓動程序的py文件(start.py):等同於此命令(scrapy crawl xxx -o xxx.json)

三、開發準備

1.在pycharm工具setting中安裝scrapy插件
2.項目右鍵選擇打開終端
在這裏插入圖片描述
3.在終端中輸入爬蟲創建命令
在這裏插入圖片描述
執行成功後在項目目錄下生成爬蟲項目
在這裏插入圖片描述
項目結構如下
在這裏插入圖片描述
3.各個文件功能介紹
(1)iterms.py是用於封裝爬蟲爬取內容的實體,具體如下:

import scrapy


class PachongItem(scrapy.Item):  
    # define the fields for your item here like:
    date = scrapy.Field()
    open = scrapy.Field()
    close = scrapy.Field()
    height = scrapy.Field()
    low = scrapy.Field()
    updownd = scrapy.Field()
    turnrate = scrapy.Field()
    count = scrapy.Field()

如果要集成django,使用django的持久化對象以及其數據庫操作能力的話,需要安裝scrapy_djangoitem插件,然後做如下引用

import scrapy
from scrapy_djangoitem import DjangoItem
import blog.models as m #  保證django項目與爬蟲項目在一個工程下,然後引用django的實體模型


class PachongItem(DjangoItem):  # scrapy.Item
    # define the fields for your item here like:
    # date = scrapy.Field()
    # open = scrapy.Field()
    # close = scrapy.Field()
    # height = scrapy.Field()
    # low = scrapy.Field()
    # updownd = scrapy.Field()
    # turnrate = scrapy.Field()
    # count = scrapy.Field()
    django_model = m.Spider  #  m.spider是django中定義的實體

(2)pachong_spider.py爬蟲主體方法,文件名可以自定義

from datetime import datetime
from decimal import Decimal

import scrapy

import pachong.items as items
# from items import PachongItem


# 命令行創建爬蟲項目命令:scrapy startproject 項目名稱
class PobotSpider(scrapy.Spider):
    # 爬蟲的名稱,也就是該文件名稱,不能亂寫,寫其他的會報錯:找不到爬蟲文件
    name = 'pachong_spider'
    # 爬蟲允許抓取的域名
    allowed_domains = ['quotes.money.163.com']
    # 爬蟲抓取數據地址,給調度器
    start_urls = ['http://quotes.money.163.com/trade/lsjysj_600051.html?year=2018&season=1']

    # *args(多個參數無key值,字符串列表), **kwargs(多個參數有key值,字典列表)
    def __init__(self, *args, **kwargs):
        super(PobotSpider, self).__init__(*args, **kwargs)
        url = 'http://quotes.money.163.com/trade/lsjysj_600051.html?year='+kwargs['year']+'&season='+kwargs['jd']
        self.start_urls = [url]
        print(self.start_urls)

    def parse(self, response):
        # # 打印返回結果
        # print(response.text)
        # xpath語法:根據抓取網頁的目錄結構, 等到上面結果, 意思是選取class爲article的div下, class爲grid_view的ol下的所有li標籤
        # extract() 獲取真實內容;extract_first()獲取第一個匹配的真是內容;//全局匹配包含子節點孫子節點,全級別搜索;"/"根節
        # 點匹配子節點不包含孫子節點,檢索一級標籤;屬性匹配div[@id="name"];text()匹配標籤內的文本;.get()/.getall()獲取第一個匹配的文本/全部匹配的文本
        # response.xpath(’//div[@class=“col1”]/div’)[0].xpath(’./a/div/span/text()’).getall();./或.//當前選擇的標籤內容中搜索
        # ;../或..//父級標籤內搜索子或孫子標籤;
        # response.xpath(’//div[@class=“col1”]/div’)[0].xpath(’./a/div/span/@class’).getall()獲取選擇標籤的class屬性值
        # 支持切片
        stock_list = response.xpath("//div[@class='area']//div[@class='inner_box']//table//tr")
        for index, i_item in enumerate(stock_list):
            if index == 0:
                continue
            stock_item = items.PachongItem()
            # 1.DoubanItem() 模型初始化
            # 2.douban_item['serial_number'] 設置模型變量serial_number值,
            # 3.i_item.xpath(".//div[@class='item']//em/text()") 對返回結果進一步篩選, 並且以"." 開頭表示拼接, 以text()結束表示獲取其信息
            # 4.extract_first() xpath匹配器返回的是一個list,即使只有一個值也是放在list中的,因此要想直接獲取字符串,需要獲取結果的第一個值
            # 也就是用extract_fist(),也可以用索引xpath()[0]
            stock_item['date'] = datetime.strptime(i_item.xpath(".//td[1]/text()").extract_first(), '%Y-%m-%d')
            stock_item['open'] = Decimal(i_item.xpath(".//td[2]/text()").extract_first())
            stock_item['height'] = Decimal(i_item.xpath(".//td[3]/text()").extract_first())
            stock_item['low'] = Decimal(i_item.xpath(".//td[4]/text()").extract_first())
            stock_item['close'] = Decimal(i_item.xpath(".//td[5]/text()").extract_first())
            stock_item['updownd'] = Decimal(i_item.xpath(".//td[7]/text()").extract_first())
            stock_item['count'] = Decimal(i_item.xpath(".//td[10]/text()").extract_first())
            stock_item['turnrate'] = Decimal(i_item.xpath(".//td[11]/text()").extract_first())
            # yield 就是一個集合對象,可以將多次返回的值存入到一個集合迭代器中。
            yield stock_item

(3)pipelines.py用於持久化爬取的數據,並進行清洗過濾,可以有多個pipeline
不集成django的寫法如下:

import pymysql


# pipeline管道,用於持久化爬取的數據,並進行清洗過濾,可以有多個pipeline
# 繼承object類,重寫了幾個方法
# 可以多個pipeline 實現類,通過settings.py中的ITEM_PIPELINES配置格式:‘類路徑’:級別(整型數值),與優先級係數來判定哪個先執行
# 帶@classmethod的是類方法,類方法不實例化,可以理解爲全局方法,重寫時也需要帶此註解
class PachongPipeline(object):
     movieInsert = '''insert into blog_spider(date,open,close,height,low,updownd,turnrate,count)
                                 values('{date}','{open}','{close}','{height}','{low}',
                                 '{updownd}','{turnrate}','{count}')'''

    def __init__(self):
        self.conn = pymysql.connect(user='root', password='@bjive321',
                                    host='59.110.138.8', port=3306,
                                    database='blog', use_unicode=True,
                                    charset='utf8')
        self.cursor = self.conn.cursor()
        self.conn.autocommit(True)

    def process_item(self, item, spider):
         # pymysql.escape_string用於轉譯,將字符串內的轉義字符,轉譯
         sql_text = self.movieInsert.format(
             date=datetime.datetime.strptime(pymysql.escape_string(item['date']), '%Y-%m-%d'),
             open=Decimal(pymysql.escape_string(item['open'])),
             close=Decimal(pymysql.escape_string(item['close'])),
             height=Decimal(pymysql.escape_string(item['height'])),
             low=Decimal(pymysql.escape_string(item['low'])),
             updownd=Decimal(pymysql.escape_string(item['updownd'])),
             turnrate=Decimal(pymysql.escape_string(item['turnrate'])),
             count=Decimal(pymysql.escape_string(item['count'])))
         self.cursor.execute(sql_text)

    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()

集成django寫法如下:

import pymysql


# pipeline管道,用於持久化爬取的數據,並進行清洗過濾,可以有多個pipeline
# 繼承object類,重寫了幾個方法
# 可以多個pipeline 實現類,通過settings.py中的ITEM_PIPELINES配置格式:‘類路徑’:級別(整型數值),與優先級係數來判定哪個先執行
# 帶@classmethod的是類方法,類方法不實例化,可以理解爲全局方法,重寫時也需要帶此註解
class PachongPipeline(object):
    # movieInsert = '''insert into blog_spider(date,open,close,height,low,updownd,turnrate,count)
    #                             values('{date}','{open}','{close}','{height}','{low}',
    #                             '{updownd}','{turnrate}','{count}')'''

    def __init__(self):
        self.conn = pymysql.connect(user='root', password='@bjive321',
                                    host='59.110.138.8', port=3306,
                                    database='blog', use_unicode=True,
                                    charset='utf8')
        self.cursor = self.conn.cursor()
        self.conn.autocommit(True)

    def process_item(self, item, spider):
        # # pymysql.escape_string用於轉譯,將字符串內的轉義字符,轉譯
        # sql_text = self.movieInsert.format(
        #     date=datetime.datetime.strptime(pymysql.escape_string(item['date']), '%Y-%m-%d'),
        #     open=Decimal(pymysql.escape_string(item['open'])),
        #     close=Decimal(pymysql.escape_string(item['close'])),
        #     height=Decimal(pymysql.escape_string(item['height'])),
        #     low=Decimal(pymysql.escape_string(item['low'])),
        #     updownd=Decimal(pymysql.escape_string(item['updownd'])),
        #     turnrate=Decimal(pymysql.escape_string(item['turnrate'])),
        #     count=Decimal(pymysql.escape_string(item['count'])))
        # self.cursor.execute(sql_text)
        item.save()

    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()

(4)settings.py用於爬蟲配置信息的設置
如果集成django配置如下:

import os
import sys
import django

#======集成django需要增加以下內容,不集成則不需要===start======
sys.path.append(r"E:\pycharm\pystudy\blogs")  # django項目的絕對路徑
os.environ['DJANGO_SETTINGS_MODULE'] = 'blogs.settings'  # Django工程名.settings
# 手動初始化Django:
django.setup()
#=====end=================================
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36'

ROBOTSTXT_OBEY = False

DOWNLOAD_DELAY = 0.5

#可以配置多個管道
ITEM_PIPELINES = {
   'pachong.pipelines.PachongPipeline': 300,
}

(5)創建一個main.py用於啓動爬蟲

cmdline.execute('scrapy crawl pachong_spider'.split())

4.啓動爬蟲
在這裏插入圖片描述
ok
5.遇到的問題解決
引入包的時候可能會找不到路徑,在工具,File->Settings->python console選中右側紅框內容
在這裏插入圖片描述
然後右鍵項目中引用涉及到的目錄文件夾,選擇如下:
在這裏插入圖片描述
即可。

四、django啓動爬蟲

如果需要在django頁面啓動爬蟲的話需要安裝scrapyd,安裝方法請自定網查
安裝好後執行scrapyd啓動服務,默認端口是6800
在這裏插入圖片描述
在django頁面增加一個按鈕,執行start請求,對應url與view中加入相關配置
啓動方法代碼如下:

#在線啓動爬蟲
def start_scrapy(request):
    # 獲取頁面傳參,要區分請求類型是POST還是GET,不同請求用不同的方法接收參數
    year = request.POST.get('year')
    jd = request.POST.get('jd')
    url = 'http://127.0.0.1:6800/schedule.json'
    # spider是執行scrapy list返回的名稱,參數問題:除了內置key的參數外如project,spider等,其他參數均由爬蟲初始化函數的kwargs接收
    # 同時jobid也有kwargs接收,**kwargs是接收字典型的參數,帶有key值的
    data = {'project': 'pachong', 'spider': 'pachong_spider', 'year': year, 'jd': jd}
    print(requests.post(url=url, data=data))
    return JsonResponse({'result': 'ok'})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章