Scrapy初體驗

學了python之后一直在給自己找點兒什么需求練練手,爬蟲是學python最快的途徑,就想著爬點豆瓣電影的數據吧,在經過了一系列重復造輪子之后,決定體驗一下scrapy。

scrapy的架構圖:

scrapy_architecture.png
1、引擎(ScrapyEngine): 用來處理整個系統的通訊,數據流處理, 觸發事務(框架核心)。
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流程:

1.Spider將初始url告訴Engine,Engine將url添加到調度器的請求隊列中
2.Engine從調度器隊列中拿到下一個要請求的url,交給下載器(下載器中間件可以設置代理之類。。),下載器下載網頁內容,交還給引擎
3.Engine將從下載器拿到的網頁內容,交給spider,spider爬取所需要的內容,生成item交還給Engine,如果需要繼續爬取,將新的url告訴Engine,并添加到調度器的請求隊列中
4.pipeline 從Engine拿到爬取的實體進行處理

python&scrapy安裝:

windows下安裝python+scrapy

開始

創建項目:

scrapy startproject 項目名稱

目錄介紹:

.cfg         項目配置文件  定義了項目配置文件路徑,部署信息等內容

items.py     定義item數據結構的地方

settings.py  項目的設置文件,定義項目的全局設置 

生成spiders文件:

在spiders目錄中進入命令行輸入  scrapy genspider 爬蟲名 要爬取的域名

刷新項目文件目錄

spider文件中:
    name : 爬蟲的名稱
    start_urls : 為初始爬蟲目錄,就是第一次爬取的地址url

執行爬蟲文件 :

scrapy crawl 爬蟲名稱

爬取豆瓣電影網站內容

在項目磁盤目錄下打開命令行輸入

scrapy startproject douban_demo

生成項目文件

修改settings.py文件中USER_AGENT和ROBOTSTXT_OBEY:不然請求會被攔截

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'

ROBOTSTXT_OBEY = False

在spiders目錄中進入命令行輸入

scrapy genspider douban_spider movie.douban.com

之后會在spiders目錄中生成一個douban_spider.py 的文件,修改start_urls:

start_urls = ['http://movie.douban.com/top250']

打開頁面,我們接下來要抓取這些數據

douban.png

在items.py中創建我們的數據模型:

class DouBanItem(scrapy.Item):
    #電影編號
    movie_num = scrapy.Field()
    #電影封面地址
    movie_imgurl = scrapy.Field()
    #電影名稱
    movie_name = scrapy.Field()
    #電影參與人員
    movie_person = scrapy.Field()
    #電影評分
    movie_grade = scrapy.Field()
    #電影口號
    movie_slogen = scrapy.Field()

douban_spider.py中 的 parse方法,就是我們寫爬蟲代碼的地方

檢查頁面,查看頁面標簽詳情,可以看到頁面的標簽結構

爬取數據:

movies = response.css('div.item')
for movie in movies:
    movie_num = movie.css('em::text').extract_first()
    movie_imgurl = movie.css('img::attr(src)').extract_first()
    movie_name = movie.css('.title::text').extract_first()
    movie_person = movie.css('.bd p::text').extract_first()
    movie_grade = movie.css('.rating_num::text').extract_first()
    movie_slogen = movie.css('.inq::text').extract_first()

    doubanItem = DouBanItem()
    doubanItem['movie_num'] = movie_num
    doubanItem['movie_imgurl'] = movie_imgurl
    doubanItem['movie_name'] = movie_name
    doubanItem['movie_person'] = movie_person
    doubanItem['movie_grade'] = movie_grade
    doubanItem['movie_slogen'] = movie_slogen

將爬取到的數據加入pipline管道

yield doubanItem

將數據寫入txt文本文件

with open('movie_info.txt','a+',encoding='utf-8') as f:
    f.write(movie_num+" : "+movie_name+" : \t"+movie_grade+"\n")
    f.write('封面圖片地址 : '+movie_imgurl+'\n')
    f.write('參與人員 : '+movie_person+'\n')
    f.write(movie_slogen+"\n")
    f.write('\n-----------------------------------------\n')

    使用a+追加方式,編碼使用utf-8,打開文本文件,往里寫入

繼續爬取下一頁數據:

next_page = response.css('span.next a::attr(href)').extract_first()
if next_page is not None:
    realUrl = "http://movie.douban.com/top250"+next_page
    realUrl = response.urljoin(realUrl)
    yield scrapy.Request(realUrl,callback=self.parse)

根據css找到下一頁按鈕中的地址,這個頁面是需要拼接host地址,如果 is not None 表示還有下一頁,
urljoin(url)將地址添加到調度器請求隊列中,scrapy.Request(realUrl,callback=self.parse)之情請求,設置回調使用當前parse方法作為返回數據的處理方法

用爬取到的數據,生成json文件

在命令行中(可以使用pycharm中的Terminal命令行)執行爬蟲文件

scrapy crawl douban_spider -o douban.json

'douban_spider'是douban_spider.py中name字段的值

執行完本地就會生成一個json文件

用爬取到的數據,生成csv格式文件

在命令行中(可以使用pycharm中的Terminal命令行)執行爬蟲文件

scrapy crawl douban_spider -o douban.csv

'douban_spider'是douban_spider.py中name字段的值

執行完本地就會生成一個csv文件

爬取數據存儲MongoDB

首先在settings.py文件中打開 pipeline開關,并在最后面配置mongodb

ITEM_PIPELINES = {
  'scrapy_demo.pipelines.ScrapyDemoPipeline': 300,
}
mongo_host = '127.0.0.1'
mongo_port = 27017
mongo_db_name = 'douban'
mongo_db_collection = 'douban_movie

在pipelines.py中編寫代碼
首先導入settings中的mongodb配置和mongodb

import pymongo
from scrapy_demo.settings import mongo_db_collection,mongo_db_name,mongo_host,mongo_port

在構造函數中傳入配置參數:

def __init__(self):
    # 端口號
    port = mongo_port
    # 基地址
    host = mongo_host
    # 數據庫名
    dbname = mongo_db_name
    # 表名
    sheetname = mongo_db_collection
    # 創建client
    client = pymongo.MongoClient(host=host,port=port)
    # 指定數據庫
    mydb = client[dbname]
    # 找到表
    self.post = mydb[sheetname]

在process_item方法中進行數據插入的編寫

def process_item(self, item, spider):
    # 將模型轉化為字典
    data = dict(item)
    # 將字典數據插入mongodb
    self.post.insert(data)
    return item

運行之后就可以在數據庫中看到咱們已經添加了數據

0180912140030.png

對爬蟲進行偽裝

設置代理ip

為了不讓要爬取的網站發現我們的爬取動作,需要對爬蟲進行一些偽裝,
我們可以通過下載器中間件(Downloader Middlewares)對我們的請求進行偽裝

將settings.py中的DOWNLOADER_MIDDLEWARES配置打開(543為優先級,數字越小,優先級越高)

DOWNLOADER_MIDDLEWARES = {
   'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
}

在middlewares.py文件中進行編寫

創建一個中間件:

class DoubanProcess(object):
    def process_request(self,request,spider):
        request.meta['proxy'] = '你的代理ip地址'
        # 需要登錄的話-因為加密需要byte類型,所以需要在前面加b
        name_pwd = b'用戶名:密碼'
        # 對用戶名密碼加密
        encode_name_pwd = base64.b64decode(name_pwd)
        # 設置http頭
        request.headers['Proxy-Authorization'] = 'Bisic ' + encode_name_pwd.decode()

將你的中間件添加到settings.py的DOWNLOADER_MIDDLEWARES配置中

DOWNLOADER_MIDDLEWARES = {
   # 'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
   'scrapy_demo.middlewares.DoubanProcess': 543,
}

設置隨機User-Agent

在middlewares.py文件中進行編寫

創建一個中間件:

class DoubanUserAgent(object):
def process_request(self,request,spider):
    # user-agent列表
    USER_AGENT_LIST = [
        'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',
        'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',
        'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',
        'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',
        'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',
        'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0',
        'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)',
        'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'
    ]
    # 使用random隨機從列表中選擇一個user-agent
    agent = random.choice(USER_AGENT_LIST)
    # 修改請求頭
    request.headers['User_Agent'] = agent

將user-agent中間件添加到 settings.py的DOWNLOADER_MIDDLEWARES配置中(優先級不能相同)

DOWNLOADER_MIDDLEWARES = {
   # 'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
   'scrapy_demo.middlewares.DoubanProcess': 543,
   'scrapy_demo.middlewares.DoubanUserAgent': 544,
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。