整理自思維導圖
Scrapy一個開源和協作的框架
是基於twisted框架開發而來,twisted是一個流行的事件驅動的python網絡框架。因此Scrapy使用了一種非阻塞(又名異步)的代碼來實現並發。整體架構大致如下
命令行工具
常用的全局命令:
項目命令:
項目目錄
解析器:
組件詳解
spider:
1.自己修改起始url
2.pipeline
使用前先配置:
優先級越小越先執行
方法:
process是一直執行的,但是open_spider是第一次打開爬蟲的時候執行
close_spider是關閉爬蟲的時候執行
如果有兩個pipline
就是先執行上面那個process_item,在執行下面的process_item,一人一下
如果想上面執行,下面不執行,就需要在return里面,觸發一個異常,這樣就不會執行下面的proocess_item了
每個方法后面都有一個spider參數,可以用這個區分不同的爬蟲程序
3.去重規則
4.自定制命令:
這個spider_list就是我們自己要找的所有的爬蟲
重點是這幾個代碼,是爬蟲源碼的入口,我們可以通過這幾個命令,都可以順着找到爬蟲是怎么做的
5.scrapy的信號
需要這樣配置:
6.中間件
scrapy的中間件分為下載中間件和爬蟲中間件,重點介紹下載中間件
下載中間件:
使用自己的中間件,得先配置:
下載中間件有三個方法:
其中process_request的返回值,
返回一個request對象,將會直接返回到調度器,重新開始訪問url,如果一直這樣,就變成死循環了,,可以用來做重試,比如沒有下載成功,就再重新走一次
如果想返回一個response:
首先應該返回的是一個response對象,而不是自己瞎寫的什么返回值
def process_response(self, request, response, spider): """ spider處理完成,返回時調用 :param response: :param result: :param spider: :return: Response 對象:轉交給其他中間件process_response Request 對象:停止中間件,request會被重新調度下載 raise IgnoreRequest 異常:調用Request.errback """ from scrapy.http.response import Response #response對象是從這里導入的 return Response(url='http://www.baidu.com',request=request)
如果返回一個response,結果是所有的response都執行了,這個跟Django1.7,1.8的做法是一樣的,但是和現在的版本不一樣
應用:1.緩存,自己返回了response,就不執行后續代碼了
2.設置代理,
3.為所有的請求設置請求頭
說一說這個代理,scrapy默認是支持的,但是他的代理是需要配置環境變量的,在程序運行之前,是先從一個地方拿代理,所以要先去這個地方寫好,這個地方就是環境變量
os.environ就是當前的環境變量
詳細可以參照http://www.cnblogs.com/wupeiqi/articles/6229292.html
設置請求頭:
爬蟲中間件:
class SpiderMiddleware(object): def process_spider_input(self,response, spider): """ 下載完成,執行,然后交給parse處理 :param response: :param spider: :return: """ pass def process_spider_output(self,response, result, spider): """ spider處理完成,返回時調用 :param response: :param result: :param spider: :return: 必須返回包含 Request 或 Item 對象的可迭代對象(iterable) """ return result def process_spider_exception(self,response, exception, spider): """ 異常調用 :param response: :param exception: :param spider: :return: None,繼續交給后續中間件處理異常;含 Response 或 Item 的可迭代對象(iterable),交給調度器或pipeline """ return None def process_start_requests(self,start_requests, spider): """ 爬蟲啟動時調用 :param start_requests: :param spider: :return: 包含 Request 對象的可迭代對象 """ return start_requests
7.配置相關
scrapy支持離線操作,即緩存頁面信息,需要這樣配置:
實戰:爬取天貓Python書籍信息
3.修改起始url
還有注意是用yield,對於這種io操作,要想讓scrapy識別,必須用yield返回
4.解析函數
有兩個,因為需要到詳情頁,所以需要一個解析首頁的函數,一個解析詳情頁的函數
首頁的函數:
def start_requests(self): url = 'https://list.tmall.com/search_product.htm?' parmas = { 'q': self.q, # 's':self.s } url = url+urlencode(parmas,encoding='utf-8') yield Request(url,callback=self.parse_index)#暫時沒有cookie,但是headers要加,在settings中改
爬取詳情頁的邏輯也差不多,就不多說了
5.寫item
6.把數據保存到數據庫
這個pymysql的具體操作:
完整代碼:
import pymysql from .. import settings conn = pymysql.connect( host = settings.MYSQL_HOST, port=settings.MYSQL_PORT, user=settings.MYSQL_USER, password=settings.MYSQL_PWD, db=settings.MYSQL_DB, charset='utf8' ) cursor = conn.cursor() class Sql(object): #插入數據 @staticmethod def insert_table_goods(title,price,store): sql = 'insert into goods(title,price,store) VALUES(%s,%s)' cursor.execute(sql,args=(title,price,store)) conn.commit() #去重 @staticmethod def is_repeat(title,store): sql='select count(1) from goods WHERE title=%s AND store=%s' cursor.execute(sql,args=(title,store)) res = cursor.fetchone()[0] if res>=1: return True
最后整理一下scrapy的操作流程:
- name - start_url, start_requests - request對象,封裝:請求相關和回調函數 - reponse對象,封裝:響應相關和請求相關 - 獲取start_requests中返回的【迭代器】 - 執行爬蟲中間件 process_start_requests - 去重規則:request_seen - 放入調度器,requests可能會有序列化操作,===> enqueue_request - 去調度器中獲取任務, ===> next_request - 下載中間件 - 設置請求頭 - 代理【內置 _proxy;自定義下載中間件】 - 自己下載返回response - 爬蟲的回調函數 parse yield request對象 yield item對象 - pipeline - 擴展,基於信號 - Https
好了,關於scrapy_redis的使用,請關注我下一篇博客