歡迎關注微信公衆號:FSA全棧行動 👋javascript
Scrapy 是一個 python 編寫的,被設計用於爬取網絡數據、提取結構性數據的開源網絡爬蟲框架。html
補充:Scrapy 使用了 Twisted 異步網絡框架,能夠加快下載速度java
其流程描述以下:node
注意:python
模塊 | 做用 | 是否實現 |
---|---|---|
Scrapy Engine(引擎) | 總指揮:負責數據和信號在不一樣模塊之間傳遞 | scrapy 已經實現 |
Scheduler(調度器) | 一個隊列,存放引擎發過來的 request 請求 | scrapy 已經實現 |
Downloader(下載器) | 下載把引擎發過來的 request 請求,並返回給引擎 | scrapy 已經實現 |
Spider(爬蟲) | 處理引擎發來的 response,提取數據、url,並交給引擎 | 須要手寫 |
Item Pipeline(管道) | 處理引擎傳過來的數據,好比存儲 | 須要手寫 |
Downloader Middlewares(下載中間件) | 能夠自定義的下載擴展,好比設置代理 | 通常不用手寫 |
Spider Middlewares(爬蟲中間件) | 能夠自定義 requests 請求和進行 response 過濾 | 通常不用手寫 |
注意:爬蟲中間件 和 下載中間件 只是運行邏輯的位置不一樣,做用是重複的:如替換 UA 等。git
scrapy 有 2 種安裝方式:es6
命令:github
sudo apt-get install scrapy
複製代碼
pip:web
pip/pip3 install scrapy
複製代碼
建立項目:ajax
scrapy startproject <項目名稱>
eg:
scrapy startproject myspider
複製代碼
生成一個爬蟲:
scrapy genspider <爬蟲名字> <容許爬取的域名>
eg:
cd myspider
scrapy genspider example example.com
複製代碼
爬蟲名字:做用爬蟲運行時的參數
容許爬取的域名:爲對於爬蟲設置的爬取範圍,設置以後用於過濾要爬取的 url,若是爬取的 url 與容許的域不一樣則被過濾掉
注意:執行完命令後,myspider/spiders 目錄下,會多出一個 example.py 爬蟲文件
提取數據:
根據網站結構在 spider 中實現數據採集相關內容
保存數據:
使用 pipeline 進行數據後續處理和保存
運行 scrapy
scrapy crawl <爬蟲名字>
scrapy crawl <爬蟲名字> --nolog
eg:
scrapy crawl example
複製代碼
注意 :須要在項目錄下執行命令;
--nolog
能夠關閉框架日誌信息輸出
解析並獲取 scrapy 爬蟲中的數據:利用 xpath 規則字符串進行定位和提取
response.xpath()
:返回一個相似 List 的類型,其中包含的是 selector 對象,操做和列表同樣,可是有一些額外方法:
extract()
:返回一個包含有字符串的列表extract_first()
:返回列表中的第一個字符串,列表爲空則返回 Noneresponse.url
:當前響應的 url 地址response.request.url
:當前響應對應的請求的 url 地址response.headers
:響應頭response.request.headers
:當前響應的請求頭response.body
:響應體,也就是 html 代碼,byte 類型response.status
:響應狀態碼scrapy startproject myspider
cd myspider
scrapy genspider itcast itcast.cn
複製代碼
在/myspider/myspider/spiders/itcast.py 中修改內容以下:
import scrapy
class ItcastSpider(scrapy.Spider):
name = 'itcast'
# 2.檢查域名
allowed_domains = ['itcast.cn']
# 1.修改起始url
start_urls = ['http://itcast.cn/channel/teacher.shtml'] # 設置起始的url,咱們只須要設置就好,一般會被自動的建立成請求發送
# 3.在parse方法中實現爬取邏輯
def parse(self, response):
# 解析方法,一般用於起始url對應響應的解析
# 定義對於網站的相關操做
# with open('itcast.html', 'wb') as f:
# f.write(response.body)
# 獲取全部老師節點
node_list = response.xpath('//div[@class="li_txt"]')
# 遍歷老師節點列表
for node in node_list:
temp = {}
# xpath方法返回的是選擇器對象列表,extract()用於從選擇器對象中提取數據
# temp['name'] = node.xpath('./h3/text()')[0].extract()
# temp['title'] = node.xpath('./h4/text()')[0].extract()
# temp['desc'] = node.xpath('./p/text()')[0].extract()
# xpath結果爲只含有一個值的列表,可使用extract_first(),若是爲多個值則使用extract()
temp['name'] = node.xpath('./h3/text()').extract_first()
temp['title'] = node.xpath('./h4/text()').extract_first()
temp['desc'] = node.xpath('./p/text()').extract_first()
# {'name': [<Selector xpath='./h3/text()' data='黃老師'>], 'title': [<Selector xpath='./h4/text()' data='高級講師'>], 'desc': [<Selector xpath='./p/text()' data='15年+的軟件開發與教學經驗,參與中國聯通VOP系統,中國聯通在線計費系統...'>]}
# extract()以後:
# {'name': '黃老師', 'title': '高級講師', 'desc': '15年+的軟件開發與教學經驗,參與中國聯通VOP系統,中國聯通在線計費系統,道路交通事故救助基金管理系統等的開發工做;\r\n擁有豐富的教學經驗。'}
print(temp)
yield temp
複製代碼
注意:
scrapy.Spider
爬蟲類中必須有名爲 parse 的解析allowed_domains
範圍內,可是 start_urls
中的 url 地址不受這個限制parse()
函數中使用 yield
返回數值。process_item()
方法process_item()
方法處理完 item 以後必須返回給引擎這裏直接使用建立項目時默認建立好的管道類:/myspider/myspider/pipelines/MyspiderPipeline,修改內容以下:
import json
class MyspiderPipeline:
def __init__(self):
self.file = open('itcast.json', 'w')
def process_item(self, item, spider):
# print('item:', item)
# 將字典數據序列化
json_data = json.dumps(item, ensure_ascii=False) + ',\n'
# 將數據寫入文件
self.file.write(json_data)
# 默認使用完管道以後須要將數據返回給引擎
return item
def __del__(self):
self.file.close()
複製代碼
ITEM_PIPELINES = {
'myspider.pipelines.MyspiderPipeline': 300,
# 'myspider.pipelines.MyspiderPipelineOther': 301,
}
複製代碼
.
進行分割,分別爲:項目目錄.文件.管理類
。在控制檯運行以下命令便可運行爬蟲:
scrapy crawl itcast
scrapy crawl itcast --nolog
複製代碼
一般在項目開發過程當中,須要在 items.py
中進行數據建模
在 items.py
文件中定義發提取的字段:
import scrapy
class MyspiderItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field() # 講師的名字
title = scrapy.Field() # 講師的職稱
desc = scrapy.Field() # 講師的介紹
# if __name__ == '__main__':
# item = MyspiderItem()
# item['name'] = 'lqr' # ok
# item['nama'] = 'lqr' # KeyError: 'MyspiderItem does not support field: nama'
複製代碼
注意:
scrapy.Item
能夠理解爲一個更高級的 「字典」,能夠對鍵名進行限制、校驗。但切記它不是字典,若是你須要對字典進行操做,可使用dict()
將scrapy.Item
進行強制轉換。
模板類定義之後,須要在爬蟲中導入而且實例化,以後的使用方法和字典相同:
# 若是報包報錯有2種解決辦法:
# 一、PyCharm以myspider爲根目錄從新打開項目
# 二、不以myspider爲根目錄的話,能夠右鍵myspider-->Make Directory as-->Sources Root
from myspider.items import MyspiderItem
def parse(self, response):
item = MyspiderItem()
...
item['name'] = node.xpath('./h3/text()').extract_first()
item['title'] = node.xpath('./h4/text()').extract_first()
item['desc'] = node.xpath('./p/text()').extract_first()
...
yield item
複製代碼
建立項目
scrapy startproject 項目名
複製代碼
明確目標
建立爬蟲
建立爬蟲
scrapy genspider 爬蟲名 容許的域
複製代碼
編寫爬蟲
修改start_urls
檢查修改allowed_domains
編寫解析方法
複製代碼
保存數據
pipelines.py
文件中定義對數據處理的管道settings.py
文件中註冊啓用管道肯定 url 地址
構造請求
scrapy.Request(url, callback)
複製代碼
callback
:指定解析函數名稱,表示該請求返回的響應使用哪個函數進行解析把請求交給引擎
scrapy startproject wangyi
cd wangyi
scrapy gespider job 163.com
複製代碼
import scrapy
class WangyiItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
link = scrapy.Field()
depart = scrapy.Field()
category = scrapy.Field()
type = scrapy.Field()
address = scrapy.Field()
num = scrapy.Field()
date = scrapy.Field()
複製代碼
import scrapy
from wangyi.items import WangyiItem
class JobSpider(scrapy.Spider):
name = 'job'
# 2.檢查修改allowed_domains
allowed_domains = ['163.com']
# 1.修改start_urls
start_urls = ['https://hr.163.com/position/list.do']
def parse(self, response):
# 提取數據
# 獲取全部職位節點列表
node_list = response.xpath('//*[@class="position-tb"]/tbody/tr')
# 遍歷節點列表
for num, node in enumerate(node_list):
# 設置過濾條件,將目標節點獲取出來
if num % 2 == 0:
item = WangyiItem()
item['name'] = node.xpath('./td[1]/a/text()').extract_first()
# item['link'] = 'https://hr.163.com' + node.xpath('./td[1]/a/@href').extract_first()
# response.urljoin()用於拼接相對路徑的url,能夠理解爲自動補全
item['link'] = response.urljoin(node.xpath('./td[1]/a/@href').extract_first())
item['depart'] = node.xpath('./td[2]/text()').extract_first()
item['category'] = node.xpath('./td[3]/text()').extract_first()
item['type'] = node.xpath('./td[4]/text()').extract_first()
item['address'] = node.xpath('./td[5]/text()').extract_first()
item['num'] = node.xpath('./td[6]/text()').extract_first().strip()
item['date'] = node.xpath('./td[7]/text()').extract_first()
# print(item)
yield item
# 模擬翻頁
part_url = response.xpath('/html/body/div[2]/div[2]/div[2]/div/a[last()]/@href').extract_first()
# 判斷終止條件
if part_url != 'javascript:void(0)':
next_url = response.urljoin(part_url)
# 構建請求對象,而且返回給引擎
yield scrapy.Request(
url=next_url,
callback=self.parse
)
複製代碼
注意:引擎根據爬蟲
yield
的對象類型,將對象分配給對應的模塊處理,好比:若是是模板類對象或字典,則會交給管道(Item Pipeline);若是是 Request 對象,則會交給隊列(Scheduler)。
import json
class WangyiPipeline:
def __init__(self):
self.file = open('wangyi.json', 'w')
def process_item(self, item, spider):
item = dict(item)
str_data = json.dumps(item, ensure_ascii=False) + ',\n'
self.file.write(str_data)
return item
def __del__(self):
self.file.close()
複製代碼
ITEM_PIPELINES = {
'wangyi.pipelines.WangyiPipeline': 300,
}
複製代碼
scrapy crawl job --nolog
複製代碼
能夠在 settings 中設置 ROBOTS 協議
# False表示忽略網站的robots.txt協議,默認爲True
ROBOTSTXT_OBEY = False
複製代碼
能夠在 settings 中設置 User-Agent:
# scrapy發送的每個請求的默認UA都是設置的這個User-Agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
複製代碼
scrapy.Request(url[, callback, method="GET", headers, body, cookies, meta, dont_filter=False])
複製代碼
注意:中括號[]裏的參數爲可選參數
參數解釋:
meta 的使用:
meta 的注意事項:
使用舉例:
def parse(self, response):
...
yield scrapy.Request(detail_url, callback=self.parse_detail, meta={'item': item})
...
def parse_detail(self,response):
# 獲取以前傳入的item
item = response.meta['item']
複製代碼
應用場景:
scrapy 中 start_url 是經過 start_requests 來進行處理的,可能經過重寫該方法讓 start_url 攜帶上請求頭信息,實現代碼以下:
import scrapy
class Git1Spider(scrapy.Spider):
name = 'git1'
allowed_domains = ['github.com']
start_urls = ['https://github.com/GitLqr']
def start_requests(self):
""" 重寫start_requests,發送攜帶cookies的Request。 默認start_requests只是普通的get請求,不會攜帶自定義的頭信息 """
url = self.start_urls[0]
temp = '_octo=GH1.1.1045146750.1615451260; _device_id=cd8d64981fcb3fd4ba7f587873e97804'
# 把cookies字符串轉成字典
cookies = {data.split('=')[0]: data.split('=')[-1] for data in temp.split('; ')}
yield scrapy.Request(
url=url,
callback=self.parse,
cookies=cookies
)
def parse(self, response):
print(response.xpath('/html/head/title/text()').extract_first())
複製代碼
注意:
scrapy.Request 發送 post 請求有兩種方式:
經過 scrapy.Request()
指定 method、body 參數來發送 post 請求(不推薦)
使用 scrapy.FormRequest()
來發送 post 請求(推薦)
注意:
scrapy.FormRequest()
可以發送表單和 ajax 請求,參考閱讀 www.jb51.net/article/146…
舉例:
import scrapy
class Git2Spider(scrapy.Spider):
name = 'git2'
allowed_domains = ['github.com']
start_urls = ['http://github.com/login']
def parse(self, response):
username = 'GitLqr'
password = 'balabala'
# 從登陸頁面響應中解析出post數據
token = response.xpath('//input[@name="authenticity_token"]/@value').extract_first()
post_data = {
'commit': 'Sign in',
'authenticity_token': token,
'login': username,
'password': password,
'webauthn-support': 'supported',
}
print(post_data)
# 針對登陸url發送post請求
yield scrapy.FormRequest(
url='https://github.com/session',
callback=self.after_login,
formdata=post_data
)
def after_login(self, response):
yield scrapy.Request('https://github.com/GitLqr', callback=self.check_login)
def check_login(self, response):
print(response.xpath('/html/head/title/text()').extract_first())
複製代碼
注意:在 settings.py 中經過設置
COOKIES_DEBUG = True
可以在終端查看到 cookie 的傳遞過程
process_item(self, item, spider)
:
return item
open_spider(self, spider)
:在爬蟲開啓的時候僅執行一次close_spider(self, spider)
:在爬蟲關閉的時候僅執行一次注意:以上 3 個方法,能夠經過
spider.name
獲取爬蟲的名字
scrapy 的 Item Pipeline
模塊能夠有多個管道,當有一個 spider 把數據對象經過引擎交給 Item Pipeline
模塊時, Item Pipeline
模塊中的全部管道會按 settings.py
中指定的管道順序一一被執行。但不少時候,咱們須要管道針對特定爬蟲作數據存儲的,這時就須要在管道中對數據對象的來源作判斷。
注意:不一樣的 pipeline 可以對一個或多個爬蟲進行不一樣的數據處理的操做,好比一個進行數據清洗,一個進行數據的保存
舉例:
import scrapy
from wangyi.items import WangyiItem
class JobSpider(scrapy.Spider):
name = 'job'
...
def parse(self, response):
...
yield item
複製代碼
import scrapy
from wangyi.items import WangyiSimpleItem
class JobSimpleSpider(scrapy.Spider):
name = 'job_simple'
...
def parse(self, response):
...
yield item
複製代碼
class WangyiPipeline:
def open_spider(self, spider):
if spider.name == 'job':
self.file = open('wangyi.json', 'w')
def process_item(self, item, spider):
if spider.name == 'job':
item = dict(item)
str_data = json.dumps(item, ensure_ascii=False) + ',\n'
self.file.write(str_data)
return item
def close_spider(self, spider):
if spider.name == 'job':
self.file.close()
class WangyiSimplePipeline:
def open_spider(self, spider):
if spider.name == 'job_simple':
self.file = open('wangyi_simple.json', 'w')
def process_item(self, item, spider):
if spider.name == 'job_simple':
item = dict(item)
str_data = json.dumps(item, ensure_ascii=False) + ',\n'
self.file.write(str_data)
return item
def close_spider(self, spider):
if spider.name == 'job_simple':
self.file.close()
複製代碼
process_item
的方法必須 return item
,不然後一個 pipeline 取到的數據爲 None 值process_item
方法必需要有,不然 item 沒有辦法接收和處理process_item
方法接收 item 和 spider,其中 spider 表示當前傳遞 item 過來的 spideropen_spider(spider)
:可以在爬蟲開啓的時候執行一次close_spider(spider)
:可以在爬蟲關閉的時候執行一次根據 scrapy 運行流程中所在位置不一樣,對 scrapy 中間件進行分類:
scrapy 中間件的做用是:預處理 request 和 response 對象
默認狀況下,兩種中間件都在 middlewares.py
一個文件中
爬蟲中間件使用方法和下載中間件相同,且功能重複,一般使用下載中間件
注意:結合 scrapy 流程圖可方便理解
中間件使用步驟以下:
在 middlerware.py
中定義中間件類
在中間件類中,重寫處理請求或者響應的方法(以Downloader Middlewares
爲例)
process_request(self, request, spider)
當每一個 request 經過下載中間件時,該方法被調用【Scrapy Engine --> Downloader】
process_request
方法,若是全部中間件都返回 None,則請求最終被交給下載器處理。注意:沒有 return 也是返回 None。process_request
方法process_response(self, request, response, spider)
當下載器完成 http 請求,傳遞響應給引擎的時候調用【Scrapy Engine <-- Downloader】
process_response
方法process_response
方法在 settings
文件中開啓中間件,權重值越小越優先執行(同管道註冊同樣)
在 settings.py
文件中定義一個存放了大量 UA 的列表 USER_AGENT_LIST
:
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36'
USER_AGENT_LIST = [
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10',
'Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13',
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+',
'Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0',
'Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)',
'UCWEB7.0.2.37/28/999',
'NOKIA5700/ UCWEB7.0.2.37/28/999',
'Openwave/ UCWEB7.0.2.37/28/999',
'Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999',
'UCWEB7.0.2.37/28/999',
'NOKIA5700/ UCWEB7.0.2.37/28/999',
'Openwave/ UCWEB7.0.2.37/28/999',
'Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999'
]
複製代碼
注意:該
USER_AGENT_LIST
變量名能夠自定義,也能夠寫在其餘 py 文件中,寫在 settings.py 文件中,只是爲了規範而已。
在 middlewares.py
文件中定義隨機 UA 的下載中間件:
import random
from Douban.settings import USER_AGENT_LIST
class RandomUserAgentMiddleware(object):
def process_request(self, request, spider):
# print(request.headers['User-Agent'])
ua = random.choice(USER_AGENT_LIST)
request.headers['User-Agent'] = ua
複製代碼
在 settings.py
文件中配置開啓自定義的下載中間件:
DOWNLOADER_MIDDLEWARES = {
'Douban.middlewares.RandomUserAgentMiddleware': 543,
}
複製代碼
scrapy 的 Downloader 模塊只會根據請求獲取響應,但實際開發過程當中,有些頁面上的數據是經過 ajax 延遲加載出來的,Downloader 模塊沒法應對這種狀況,這時就須要用到 Selenium 來處理這類請求,等頁面渲染完成後,再把渲染好的頁面返回給爬蟲便可:
from selenium import webdriver
from scrapy.http import HtmlResponse
class SeleniumMiddleware(object):
def __init__(self):
self.driver = webdriver.Chrome()
def process_request(self, request, spider):
url = request.url
# 過濾須要使用selenium渲染的request
if 'daydata' in url:
self.driver.get(url)
time.sleep(3)
data = self.driver.page_source
self.driver.close()
# 返回HtmlResponse,請求不會達到Downloader,而是直接經過引擎交給爬蟲
response = HtmlResponse(url=url, body=data, encoding='utf-8', request=request)
return response
def __del__(self):
self.driver.quit()
複製代碼
若是文章對您有所幫助, 請不吝點擊關注一下個人微信公衆號:FSA全棧行動, 這將是對我最大的激勵. 公衆號不只有Android技術, 還有iOS, Python等文章, 可能有你想要了解的技能知識點哦~