一文搞定Scrapy和Selenium整合使用
前言
scrapy和selenium的整合使用
先定個(gè)小目標(biāo)實(shí)現(xiàn)萬(wàn)物皆可爬!我們是用scrapy框架來(lái)快速爬取頁(yè)面上的數(shù)據(jù),它是自帶并發(fā)的,速度是可以的。但是一些ajax異步的請(qǐng)求我們不能這么爬取。我們要視同selenium來(lái)進(jìn)行l(wèi)azy loading,也就是懶加載,渲染到頁(yè)面加載數(shù)據(jù)。
一、開始準(zhǔn)備

1. 包管理和安裝chrome驅(qū)動(dòng)
首先你要安裝以下包:
pip install scrapy pip install selenium == 3.0.0 pip install pymysql pip install bs4
selenium新版本有bug,用3.0的版本。
chrome驅(qū)動(dòng)的exe執(zhí)行文件,放到你項(xiàng)目的根目錄即可。下載地址:驅(qū)動(dòng)
2. 爬蟲項(xiàng)目的創(chuàng)建(舉個(gè)栗子)
創(chuàng)建項(xiàng)目
scrapy startproject cnki
您爬取的目標(biāo)網(wǎng)站
scrapy genspider cnki https://www.cnki.net
運(yùn)行爬蟲
# 運(yùn)行不導(dǎo)出(一般在pipelines做導(dǎo)出操作) scrapy crawl cnki # 針對(duì)不同的選擇可以導(dǎo)出為xlsx、json等格式文件 scrapy crawl demo -o demo.csv
3. setting.py的配置
配置數(shù)據(jù)源,如下:
DB_HOST = 'localhost' DB_PORT = 3306 DB_USER = 'root' DB_PASSWORD ='123456' DB_DATABASE = 'spider'
防止打印log日志信息
LOG_LEVEL = 'WARNING'
配置USER_AGENT(瀏覽器控制臺(tái)找一個(gè))
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36
配置DEFAULT_REQUEST_HEADERS(瀏覽器控制臺(tái)找一個(gè))
{
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
}隨機(jī)延遲
DOWNLOAD_DELAY = 3 RANDOMIZE_DOWNLOAD_DELAY=True
中間件權(quán)重配置(這些中間件給他打開 并且按照項(xiàng)目實(shí)際需求配置權(quán)重,越小越先執(zhí)行)
SPIDER_MIDDLEWARES # 蜘蛛中間件 DOWNLOADER_MIDDLEWARES # 下載中間件 ITEM_PIPELINES # 管道
二、代碼演示
1. 主爬蟲程序
1.初始化selenium (如果您不需要selenium,可以忽略這個(gè) )
def __init__(self, *args,**kwargs):
option = webdriver.ChromeOptions() # 實(shí)例化一個(gè)瀏覽器對(duì)象
option.add_argument('--headless') # 添加參數(shù),option可以是headless,--headless,-headless
self.driver = webdriver.Chrome(options=option) # 創(chuàng)建一個(gè)無(wú)頭瀏覽器
# self.driver = webdriver.Chrome() # 創(chuàng)建一個(gè)無(wú)頭瀏覽器
time.sleep(3)
super(CnkiSpider, self).__init__(*args, **kwargs)
dispatcher.connect(self.close_driver,signals.spider_closed)2.定義開始請(qǐng)求頁(yè)面
下面我只放了一個(gè)url,其實(shí)可以定義一組的然后進(jìn)行遍歷(一般是分頁(yè)url使用)
還有cookie、代理也可以在這里配置,詳情請(qǐng)看進(jìn)去看源碼(不過(guò)一般在中間件配置)
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(
# 這里可以設(shè)置多個(gè)頁(yè)面,一般用于分頁(yè)的
url=url,
)3.關(guān)閉selenium(一定要關(guān)掉)
def close_driver(self):
print("爬蟲正在退出,執(zhí)行關(guān)閉瀏覽器哦")
time.sleep(2)
self.driver.quit()4.解析頁(yè)面
這里就不多說(shuō),八仙過(guò)海各顯神通
def parse(self,response: HtmlResponse):
sel = Selector(response)
dds = sel.css('.journal > .main-w1 > dl > dd')
for dd in dds:
title = dd.css('h6 > a::attr(title)').extract_first()
link = dd.css('h6 > a::attr(href)').extract_first()
link = response.urljoin(link)
author = dd.css('.baseinfo > span > #author::attr(title)').extract_first()
abstract = dd.css('.abstract::text').extract_first()
count = dd.css('.opts > .opts-count > li > em::text').extract_first()
count = int(count)
date = dd.css('.opts > .opts-count > .date::text').extract_first()
date = date.split(':')[1]
date = datetime.datetime.strptime(date,"%Y-%m-%d")
rc = Recommend()
rc['title'] = title
rc['link'] = link
rc['author'] = author
rc['abstract'] = abstract
rc['count'] = count
rc['date'] = date
yield rc這里要注意我們yield可以返回不僅是item,也可以是Request,進(jìn)行頁(yè)面詳情的請(qǐng)求(套娃)
yield Request(
url=link, # 這是上面頁(yè)面上的鏈接,用來(lái)進(jìn)一步請(qǐng)求
callback=self.parse_detail, # 這是回調(diào)函數(shù)
cb_kwargs={'item':rc} # 這是把上面的item傳遞下來(lái)
)2. 中間件的配置
1.針對(duì)selenium
沒(méi)有selenium請(qǐng)忽略
class SeleniumDownloaderMiddleware:
def process_request(self, request , spider):
if spider.name == 'cnki':
spider.driver.get(request.url)
time.sleep(2)
print(f"當(dāng)前訪問(wèn){request.url}")
spider.driver.refresh()
time.sleep(3)
return HtmlResponse(url=spider.driver.current_url,body=spider.driver.page_source,encoding='utf-8')2.SpiderMiddleware保持默認(rèn)配置即可
3.DownloaderMiddleware可以配置cookie和代理之類的。如:
# 我自定義的解析cookie方法
def get_cookie_dict():
cookie_str = 填上你的cookie
cookie_dict = {}
for item in cookie_str.split(';'):
key, value = item.split('=',maxsplit=1)
cookie_dict[key] = value
return cookie_dict
COOKIES_DICT = get_cookie_dict()# 這是DownloaderMiddleware這是自帶的方法哈
def process_request(self, request : Request, spider):
request.cookies = COOKIES_DICT
return None3. 定義item對(duì)象
用來(lái)接受爬蟲到的數(shù)據(jù)
class Recommend(scrapy.Item):
title = scrapy.Field()
author = scrapy.Field()
abstract = scrapy.Field()
link = scrapy.Field()
count = scrapy.Field()
date = scrapy.Field()4. 定義管道
實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的導(dǎo)入(你也可以寫excel的)
class RecommendPipeline:
@classmethod
def from_crawler(cls, crawler: Crawler):
host = crawler.settings['DB_HOST']
port = crawler.settings['DB_PORT']
username = crawler.settings['DB_USER']
password = crawler.settings['DB_PASSWORD']
database = crawler.settings['DB_DATABASE']
return cls(host, port, username, password, database)
def __init__(self, host, port, username, password, database):
# 1、與數(shù)據(jù)庫(kù)建立連接
self.conn = pymysql.connect(host=host, port=port, user=username, password=password, database=database,
charset='utf8mb4')
# 2、創(chuàng)建游標(biāo)
self.cursor = self.conn.cursor()
# 3、批處理需要的容器
self.data = []
def process_item(self, item, spider):
title = item.get('title', '')
author = item.get('author', '')
abstract = item.get('abstract', '')
link = item.get('link', '')
count = item.get('count', '')
date = item.get('date', '')
# 如果要實(shí)現(xiàn)批處理:
self.data.append((title,author,abstract,link,count,date))
# 如果存夠了10條就進(jìn)數(shù)據(jù)庫(kù)
if len(self.data) == 10:
self._to_write_db()
# 然后再清空
self.data.clear()
return item
def close_spider(self, spider):
# 如果最后不滿足10條
if len(self.data) > 0:
self._to_write_db()
self.conn.close()
def _to_write_db(self):
# 作為一個(gè)實(shí)時(shí)的推薦,我希望將查到的數(shù)據(jù)作為一個(gè)temp
# 'delete from tb_recommend where 1 = 1' 刪除滿,并且主鍵自增不會(huì)從1開始
self.cursor.execute(
'truncate table tb_recommend'
)
self.cursor.executemany(
'insert into tb_recommend (title,author,abstract,link,count,date) values (%s, %s, %s, %s, %s, %s)',
self.data
)
self.conn.commit()
記得寫入setting.py,設(shè)置其權(quán)重。
*接下來(lái)您就可以按照這種方法‘愉’ ‘快’的進(jìn)行爬蟲啦?。。?*
總結(jié)
這是scrapy和selenium的具體整合使用,scrapy框架的內(nèi)容還有很多方法還沒(méi)用到,都有待開發(fā)。其次就是selenium的填充之類的操作還沒(méi)有使用,還需要去復(fù)習(xí)selenium的api。
相關(guān)文章
PyCharm運(yùn)行bash腳本的實(shí)現(xiàn)
本文主要介紹了PyCharm運(yùn)行bash腳本的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
python實(shí)現(xiàn)倒計(jì)時(shí)小工具
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)倒計(jì)時(shí)小工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
python pandas利用fillna方法實(shí)現(xiàn)部分自動(dòng)填充功能
這篇文章主要介紹了python pandas通過(guò)fillna方法實(shí)現(xiàn)部分自動(dòng)填充功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
Python?Django源碼運(yùn)行過(guò)程解析
這篇文章主要介紹了Python?Django源碼運(yùn)行過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
利用Python批量識(shí)別電子賬單數(shù)據(jù)的方法
這篇文章主要介紹了利用Python批量識(shí)別電子賬單數(shù)據(jù)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02
python區(qū)分不同數(shù)據(jù)類型的方法
這篇文章主要介紹了python區(qū)分不同數(shù)據(jù)類型的方法實(shí)例以及相關(guān)知識(shí)點(diǎn),需要的朋友們學(xué)習(xí)下。2019-10-10
詳解pycharm2020.1.1專業(yè)版安裝指南(推薦)
這篇文章主要介紹了pycharm2020.1.1專業(yè)版安裝指南,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
Python的條件語(yǔ)句與運(yùn)算符優(yōu)先級(jí)詳解
這篇文章主要介紹了Python的條件語(yǔ)句與運(yùn)算符優(yōu)先級(jí),是Python入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10

