Scrapy是一套基於Twisted的異步處理框架,是純python實現的爬蟲框架,用戶只須要定製開發幾個模塊就能夠輕鬆的實現一個爬蟲,用來抓取網頁內容或者各類圖片。python
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的爬蟲項目。打開cmd,來到要建立的目錄中輸入如下命令。異步
建立成功後,將項目導入至PyCharm中scrapy
先來看配置文件scrapy.cfg。
setting.py文件中能夠進行爬蟲配置的設置
其它設置在之後開發項目中須要時再進行介紹,這裏就不一一贅述(其實我也不太清楚,但不着急,慢慢來)
Item.py文件是用來定義存儲結構的地方。
因此編寫解析規則的spider文件在哪?是的,確實沒找到,這裏咱們要用命令行生成spider文件,來到項目目錄,輸入一下命令。
這時咱們就能夠看到目錄中已經生成了movie_spider.py文件,如今咱們就能夠在這裏寫解析規則了。
其它的我也很少作贅述,在下面的爬蟲實戰中會再詳細說明。
爬取豆瓣電影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爬蟲的一個入門,在各式各樣的需求中,爬蟲項目要比這複雜的多,並且網站的反爬機制也複雜的多,須要學的還不少,此文章是爲了加深本身的記憶和理解,也是想給剛入門的人一個參考,文章有什麼錯誤的地方,但願各位大佬指出,也但願給我一些指點和幫助