天天看點

scrapy 練習

scrapy版本:

初次學習是兩三年之前,當時使用python2安裝scrapy。scrapy版本1.7.3。

現在看安裝指南已經要求python 3.6+。scrapy版本已經是2.5.1。指南位址請點選:​​github安裝指南​​

現在使用肯定安裝新版scrapy了。安裝過程,這裡不重複。這個部落客要記錄使用scrapy開發過程。友善之後使用。本文使用python3。

由于我電腦是python2和python3環境都有。需要在執行指令前加上python3 -m。

scrapy建立項目

python3 -m scrapy startproject spidertest      

建立的項目,目錄結構如下

scrapy 練習
cd spidertest
python3 -m scrapy genspider test mp.csdn.net/mp_blog/manage/article?spm=1035.2022.3001.5448      

/spidertest/spidertest/spiders目錄下,建立了test.py檔案。

具體查找頁面中的具體元素,邏輯處理,可以在本檔案中實作。

程式代碼

# -*- coding: utf-8 -*-
import scrapy
import json


class TestSpider(scrapy.Spider):
    name = 'test'
    # 允許通路域
    allowed_domains = ['mp.csdn.net', 'bizapi.csdn.net']
    # 起始通路的url
    start_urls = ['http://mp.csdn.net/mp_blog/manage/article?spm=1035.2022.3001.5448/']
    headers = {'Connection': 'keep-alive',
               # 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
               #               'Chrome/96.0.4664.45 Safari/537.36',
               }

    def parse(self, response):
        url = 'https://blog.csdn.net/community/home-api/v1/get-business-list?page=1&size=20' \
              '&businessType=blog&orderby=&noMore=false&username=hutiewei2008'
        # header 指定頭,可以使用不同header,根據需要設定
        # callback 調用函數
        req_base = scrapy.Request(url, headers=self.headers,
                                  meta={}, callback=self.page_list, dont_filter=True)
        # 挂起
        yield req_base

    def page_list(self, response):
        # 傳回的text json轉dict 字元串的json轉成字典
        pagedict = json.loads(response.text)
        # 取字典資料
        pagedata = pagedict['data']
        pagelist = pagedata['list']
        # 循環取dict 資料
        for everypage in pagelist:
            url = everypage['url']
            print(url)
            title = everypage['title']
            view_count = everypage['viewCount']
            req_base = scrapy.Request(url, headers=self.headers, meta={'title': title, 'viewCount': view_count},
                                      callback=self.read_page, dont_filter=True)
            yield req_base
        with open('test.txt', 'a') as f:
            f.write('\r\n')
        f.close()

    @staticmethod
    def read_page(response):
        # scrapy 傳參
        title = response.meta['title']
        # 字典中,title為字元串類型 有int類型 view_count
        view_count = response.meta['viewCount']
        # 寫檔案 追加存儲保持資料
        with open('test.txt', 'a') as f:
            f.write(title + str(view_count) + '\t')
        print(title, view_count)
        f.close()
        pass      

執行程式

python3 -m scrapy list 檢視項目中爬蟲清單
python3 -m scrapy crawl test      

執行scrapy的爬蟲項目。出現下面報錯。不繼續執行爬蟲程式。

報錯1:

Forbidden by robots.txt

将setting.py中

​ROBOTSTXT_OBEY = True​

改為​

​ROBOTSTXT_OBEY = False​

繼續執行

python3 -m scrapy crawl test

程式執行成功。

報錯2:

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-2: ordinal not in range(128)

使用scrapy 1.7.3版本報此錯誤,使用python3 -m 的scrapy 2.5.1不報此錯誤。字元串亂碼問題,之前使用轉碼解決。

程式備注

header 指定頭,可以使用不同header,根據需要設定

‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36’

應該是能随機選擇的,這塊記不起

json轉dict

import json

pagedict = json.loads(response.text)

網頁傳回json格式封包,使用json.loads将json格式字元串,轉換成python的字典類型。

取字典資料

pagedata = pagedict[‘data’]

直接取dict的data标簽資料。

循環的字典資料可用for everypage in pagelist循環擷取。

scrapy傳參

使用參數meta傳參

原函數傳值:meta={‘title’: title, ‘viewCount’: view_count}

取值:

title = response.meta[‘title’]

寫檔案

with open('test.txt', 'a') as f:
        f.write(title + str(view_count) + '\t')
    f.close()