本文正在參加「Python主題月」,詳情查看 活動連接css
scrapy是一個很是成熟的爬蟲框架,裏面幾乎封裝好了開發者所須要的全部模塊,例如:request,代理,日誌,url自動去重等等,一些不太滿意的模塊也是稍加修改就行。但scrapy只能爬靜態網頁,若是須要爬動態渲染的網頁的話還須要藉助第三方組件,例如selenium或者splash.html
selenium和splash都是很是優秀的動態網頁渲染工具。但selenium與splash相比,主要有如下幾個有點:mysql
綜上幾點仍是選擇selenium好一點,但並非splash全無優勢,我以前寫過PHP的爬蟲,用的就是splash,我的意見:若是沒有特別複雜的交互,用splash仍是能夠的,splash提供的api,咱們只須要把請求頭,代理和url傳給splash,也能獲得渲染好的html.git
在終端輸入 pip install scrapy
web
scrapy startproject 項目名稱
scrapy genspider 文件名稱 域名
我執行的sql
scrapy startproject spider
複製代碼
scrapy genspider douban douban.com
複製代碼
生成的項目目錄就是這樣的chrome
spider
spider
spiders
__init__.py
douban.py
__init__.py
items.py
middlewares.py
piplines.py
settings.py
scrapy.cfg
複製代碼
spider
spider
common # 公共配置文件目錄
__init__.py
conf.py # 數據庫配置信息
models # mysql model類
__init__.py
spiders
__init__.py
douban.py
__init__.py
items.py
middlewares.py
piplines.py
settings.py
scrapy.cfg
複製代碼
瀏覽器驅動的安裝就不說了,由於每一個系統安裝方式都不同,網上各個系統的安裝方法都很詳細,也不是很難。數據庫
pip安裝selenium包api
pip install selenium
複製代碼
spider/spiders/douban.py瀏覽器
import scrapy
from selenium import webdriver
# 使用無頭瀏覽器
from selenium.webdriver.chrome.options import Options
# 無頭瀏覽器設置
chorme_options = Options()
chorme_options.add_argument("--headless")
chorme_options.add_argument("--disable-gpu")
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['douban.com']
start_urls = ['https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0']
# 實例化一個瀏覽器對象
def __init__(self):
self.browser = webdriver.Chrome(options=chorme_options)
super().__init__()
def parse(self, response):
print(response.body)
pass
def close(self, spider):
print('爬蟲結束,關閉瀏覽器')
self.browser.quit()
複製代碼
settings.py配置文件裏更改一些配置
# 更改用戶代理(也能夠設置成動態切換,我的感受不必)
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
# 關閉聽從robots協議
ROBOTSTXT_OBEY = False
# 打開下載中間件
DOWNLOADER_MIDDLEWARES = {
'spider.middlewares.SpiderDownloaderMiddleware': 543,
}
# 數據處理管道
ITEM_PIPELINES = {
'spider.pipelines.SpiderPipeline': 300,
}
複製代碼
middlewares.py中間件文件修改:
SpiderDownloaderMiddleware類的process_response方法修改,用瀏覽器驅動加載url
def process_response(self, request, response, spider):
"""
三個參數:
# request: 響應對象所對應的請求對象
# response: 攔截到的響應對象
# spider: 爬蟲文件中對應的爬蟲類的實例對象, 能夠經過這個參數拿到中的一些屬性或方法
"""
spider.browser.get(url=request.url)
# 等待加載, 能夠用顯示等待來優化.
time.sleep(1)
row_response = spider.browser.page_source
# 參數url指當前瀏覽器訪問的url(經過current_url方法獲取), 在這裏參數url也能夠用request.url
return HtmlResponse(url=spider.browser.current_url, body=row_response, encoding="utf8",
request=request)
複製代碼
至此,selenium的配置就完了
在Python中,最有名的ORM框架是SQLAlchemy,文檔齊全使用方便,同時爲高效和高性能的數據庫訪問設計,實現了完整的企業級持久模型。
數據庫配置文件spider/common/conf.py
class conf:
mysql = {
# 數據庫本地環境配置信息
'dev': {
'host': '127.0.0.1',
'database': 'test',
'user': 'user',
'password': 'passord',
'port': 3306,
},
# 測試服務器配置信息
'test': {
'host': '127.0.0.1',
'database': 'test',
'user': 'user',
'password': 'passord',
'port': 3306,
},
# 線上服務器配置信息
'prod': {
'host': '127.0.0.1',
'database': 'test',
'user': 'user',
'password': 'passord',
'port': 3306,
},
}
}
複製代碼
運行環境配置文件 spider/common/env.py
# coding:utf-8
"""
環境標識(不可隨意更改,此文件不上傳到git)
本地環境 dev
測試環境 test
線上環境 prod
"""
class env:
env = 'dev'
複製代碼
spider/models/__init__.py
文件裏添加數據庫鏈接
# -*- coding: utf-8 -*-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from spider.common.conf import conf
from spider.common.env import env
Base = declarative_base()
env = env.env
mysql = conf.mysql[env]
engine = create_engine(
url="mysql+pymysql://{user}:{password}@{host}/{database}".format(
user=mysql['user'],
password=mysql['password'],
host=mysql['host'],
database=mysql['database']),
encoding='UTF-8',
pool_size=5, # 鏈接池大小
max_overflow=10, # 超過鏈接池大小外最多建立的鏈接
pool_timeout=30, # 池中沒有線程最多等待的時間,不然報錯
pool_pre_ping=True
)
Session = sessionmaker(bind=engine)()
複製代碼
spider/models
目錄下添加Movie.py
文件
from sqlalchemy import Column, String, Integer, DateTime
from spider.models import Base
class Movie(Base):
# 表公共信息配置
__tablename__ = "movie"
# 表字段定義
id = Column(Integer, primary_key=True)
title = Column(String(100), comment='影片名')
created_at = Column(DateTime, comment='添加時間')
updated_at = Column(DateTime, comment='更新時間')
複製代碼
items.py
添加MovieItem
import scrapy
class SpiderItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass
class MovieItem(scrapy.Item):
title = scrapy.Field()
pass
複製代碼
spider/spiders/douban.py
添加數據解析
import scrapy
from selenium import webdriver
# 使用無頭瀏覽器
from selenium.webdriver.chrome.options import Options
# 無頭瀏覽器設置
from spider.items import MovieItem
chorme_options = Options()
chorme_options.add_argument("--headless")
chorme_options.add_argument("--disable-gpu")
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['douban.com']
start_urls = ['https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0']
# 實例化一個瀏覽器對象
def __init__(self):
self.browser = webdriver.Chrome(options=chorme_options)
super().__init__()
def parse(self, response):
for value in response.css('.list-wp>.list>a'):
item = MovieItem()
item['title'] = value.css('.cover-wp>img::attr(alt)').extract_first()
yield item
pass
def close(self, spider):
print('爬蟲結束,關閉瀏覽器')
self.browser.quit()
複製代碼
pipelines.py
將數據添加到數據庫
import datetime
from spider.models import Session
from spider.models.Movie import Movie
class SpiderPipeline:
"""
爬蟲被打開的時候執行
:param spider:
:return:
"""
def open_spider(self, spider):
print("爬蟲開始....")
"""
爬蟲有item傳過來的時候會被調用
:param item:
:param spider:
:return:
"""
def process_item(self, item, spider):
try:
data = Movie(title=item['title'], created_at=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
updated_at=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
Session.add(data)
Session.commit()
except():
Session.rollback()
return None
"""
爬蟲關閉的時候被調用
:param spider:
:return:
"""
def close_spider(self, spider):
# 關閉數據庫鏈接
Session.close()
print("爬蟲結束,關閉數據庫鏈接")
複製代碼
至此一個簡單的爬蟲程序就完成了,上面全部的請求都是走selenium組件的,有些靜態網頁是不須要的,在中間件裏判斷一下就好了。本篇只是簡單的封裝,完善的爬蟲程序還須要設置代理,考慮分佈式,增量爬蟲,這裏就不深刻介紹了。