Scrapy爬蟲框架的介紹,實戰

                                                Scrapy介紹

Scrapy是什麼?

Scrapy是一套基於Twisted的異步處理框架,是純python實現的爬蟲框架,用戶只須要定製開發幾個模塊就能夠輕鬆的實現一個爬蟲,用來抓取網頁內容或者各類圖片。python

Scrapy框架

Scrapy Engine:Scrapy引擎至關於一箇中樞站,負責Scheduler,Item Pipeline,Downloader和Spiders四個組件之間的通訊。例如,將接收到的Spiders的Requests發送給Scheduler,將Spiders的存儲請求發送給Item Pipeline。Scheduler發送的Requests,會被引擎提交到Downloader處理,而Downloader處理完成後會發送Responses給引擎,引擎將其發送至Spiders進行處理。mysql

Spiders:至關於一個解析器,負責接收Scrapy Engine發送過來的Responses,對其進行解析,你能夠在其內部編寫解析的規則。解析好的內容能夠發送存儲請求給Scrapy Engine。在Spiders中解析出的新的url,能夠向Scrapy Engine發送Requests請求。注意,入口url也是存儲在Spiders中。sql

Downloader:下載器即對發送過來的url進行下載,並將下載好的網頁反饋給Scrapy Engine。數據庫

Schedular:你能夠把他理解成一個對列,存儲Scrapy Engine發送過來的url,並按順序取出url發送給Scrapy Engine進行requests操做。服務器

Item Pipeline:在Item中你能夠定義你的存儲結構,方便數據存儲。而在Pipeline中,你能夠對數據進行存儲操做,例如將數據存儲至數據庫,或者以csv格式存貯本地。數據結構

Downloader Middlewares:你能夠在其中對ip進行代理,或封裝本身的頭文件,應對一些反爬蟲機制。框架

Spider Middlewares:你能夠添加代碼來處理髮送給 Spiders 的 response 及 spider 產生的 item 和 request。dom

建立scrapy爬蟲項目

第一步,咱們先來建立一個scrapy的爬蟲項目。打開cmd,來到要建立的目錄中輸入如下命令。異步

建立成功後,將項目導入至PyCharm中scrapy

先來看配置文件scrapy.cfg。

setting.py文件中能夠進行爬蟲配置的設置

其它設置在之後開發項目中須要時再進行介紹,這裏就不一一贅述(其實我也不太清楚,但不着急,慢慢來)

 

Item.py文件是用來定義存儲結構的地方。

 

因此編寫解析規則的spider文件在哪?是的,確實沒找到,這裏咱們要用命令行生成spider文件,來到項目目錄,輸入一下命令。

這時咱們就能夠看到目錄中已經生成了movie_spider.py文件,如今咱們就能夠在這裏寫解析規則了。

其它的我也很少作贅述,在下面的爬蟲實戰中會再詳細說明。

 

                                                Scrapy實戰

目標

爬取豆瓣電影top250的全部電影信息,將信息存儲至數據庫。

分析

打開網頁https://movie.douban.com/top250,分析咱們要爬取的內容。

咱們須要抓取電影的排名、名字、出品年份等信息。先在Item.py中定義數據結構。

再來分析一下網頁源碼,經過XPath規則定位到電影信息標籤

 

如今咱們就開始爬蟲

咱們如今先編寫spider文件

def parse(self, response):
        #爬取電影item
        movie_item=response.xpath("//div[@class='article']/ol/li")
        for item in movie_item:
            #建立存儲對象
            movieItem=MoviespiderItem()
            #爬取電影信息
            #電影序號
            movieItem['serial_number']=item.xpath(".//div/div/em/text()").extract_first()
            #電影名稱
            movieItem['film_name'] = item.xpath(".//div/div/div/a/span[@class='title']/text()").extract_first()
            #電影的年份 製做人等信息
            info_item=item.xpath(".//div/div/div[@class='bd']/p[1]/text()").extract()
            #電影製做人
            movieItem['film_maker']="".join(info_item[0].split())
            #電影年份
            movieItem['film_time'] =(''.join(info_item[1].split())).split('/')[0]
            #電影出品國家
            movieItem['film_country'] = (''.join(info_item[1].split())).split('/')[1]
            #電影類型
            movieItem['film_type'] = (''.join(info_item[1].split())).split('/')[2]
            #電影引用
            movieItem['film_quote'] = item.xpath(".//div/div/div[@class='bd']/p[2]/span/text()").extract_first()
            #電影評分
            movieItem['film_score'] = item.xpath(".//div/div/div[@class='bd']/div/span[@class='rating_num']/text()").extract_first()
            #將數據傳到pipeline
            yield movieItem
        #解析下一頁url
        next_page=response.xpath("//div[@class='paginator']/span[@class='next']/link/@href").extract()
        #判斷是否有下一頁
        if next_page:
            next_page=next_page[0]
            url=self.start_urls[0]+next_page
            #將下一頁url傳給調度器
            yield scrapy.Request(url,callback=self.parse)

咱們來運行一下,是否可以爬取到咱們所須要的內容。在cmd命令行中輸入命令

E:\code\Python\python spider\movieSpider>scrapy crawl movieSpider

爬取結果

能夠看到咱們已經爬取到了須要的內容。不過有一點須要注意,爬取前要在setting.py中設置User-Agent

既然爬取到內容,就要對內容進行存儲,先來講如何存儲到本地。以csv文件存至本地只須要輸入如下命令

E:\code\Python\python spider\movieSpider>scrapy crawl movie_spider -o movie_list.csv

運行後咱們能夠來到爬蟲目錄中查看到咱們保存的csv文件

相對於保存至本地,將咱們的爬蟲項目保存至數據庫中,更方便咱們對數據進行操做,也更適應企業要求。這裏我使用的是mysql數據庫,咱們須要先建立數據庫,在建立存貯內容的表,這一過程我就略過了,如今主要講咱們如何鏈接數據庫,並將內容進行保存。首先咱們要明確一點,咱們在Scrapy項目的哪一組件進行這一操做,在文章的開頭已經描述過,Pipeline組件是用來進行數據存儲的。咱們先來setting文件中設置咱們的mysql參數,這樣也更方便從此的操做,也更有邏輯性。

再來咱們就能夠在Pipeline中進行存儲操做了

# -*- coding: utf-8 -*-
import pymysql
from movieSpider.settings import table_name,mysql_port,mysql_db,mysql_passwd,mysql_user,mysql_host

class MoviespiderPipeline(object):
    def __init__(self):
        #鏈接數據庫
        #self.conn=pymysql.connect(host=host,port=port,user=user,password=passwd,db=database,charset='utf8')
        self.conn = pymysql.connect(host=mysql_host, user=mysql_user, password=mysql_passwd, db=mysql_db,port=mysql_port)
        #建立遊標對象
        self.cur=self.conn.cursor()

    def process_item(self, item, spider):
        #將item轉化爲dict類型
        data=dict(item)
        #將數據插入數據庫
        self.cur.execute("INSERT INTO movie_top250 (serial_number,film_name,film_country,film_time,film_type,film_maker,film_score,film_quote) VALUE (%(serial_number)s,%(film_name)s,%(film_country)s,%(film_time)s,%(film_type)s,%(film_maker)s,%(film_score)s,%(film_quote)s)",data)
        self.conn.commit()
        return item

咱們來運行一下,看是否保存到數據庫,運行前記得,要在setting中開啓pipeline

最後,咱們再來說一下基本的反爬機制,主要有設置頭文件中的User-Agent,設置代理ip,我就講講前面一種方法,由於後一種方法須要代理服務器,我買不起,也就不講了。這裏又該在哪裏寫咱們的代碼呢,咱們再回去看看文章開頭的j框架圖,顯然,咱們須要在Downloader middlwares中實現。來到middlwares.py文件中,聲明一個類,在類內的默認函數process_request中進行實現。固然,再次提醒,咱們須要在setting文件中開啓此方法。

class random_user_agent(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)']
        #從USER_AGENT_LIST隨機選擇
        user_agent=random.choice(USER_AGENT_LIST)
        request.headers["User_Agent"]=user_agent

 

                                                     總結

這篇文章只能算是scrapy爬蟲的一個入門,在各式各樣的需求中,爬蟲項目要比這複雜的多,並且網站的反爬機制也複雜的多,須要學的還不少,此文章是爲了加深本身的記憶和理解,也是想給剛入門的人一個參考,文章有什麼錯誤的地方,但願各位大佬指出,也但願給我一些指點和幫助