人生苦短,我用 Pythoncss
前文傳送門:html
小白學 Python 爬蟲(1):開篇python
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝git
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門github
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門web
小白學 Python 爬蟲(5):前置準備(四)數據庫基礎chrome
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝shell
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
小白學 Python 爬蟲(12):urllib 基礎使用(二)
小白學 Python 爬蟲(13):urllib 基礎使用(三)
小白學 Python 爬蟲(14):urllib 基礎使用(四)
小白學 Python 爬蟲(15):urllib 基礎使用(五)
小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖
小白學 Python 爬蟲(17):Requests 基礎使用
小白學 Python 爬蟲(18):Requests 進階操做
小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)
小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)
小白學 Python 爬蟲(23):解析庫 pyquery 入門
小白學 Python 爬蟲(26):爲啥買不起上海二手房你都買不起
小白學 Python 爬蟲(27):自動化測試框架 Selenium 從入門到放棄(上)
小白學 Python 爬蟲(28):自動化測試框架 Selenium 從入門到放棄(下)
小白學 Python 爬蟲(29):Selenium 獲取某大型電商網站商品信息
小白學 Python 爬蟲(31):本身構建一個簡單的代理池
小白學 Python 爬蟲(32):異步請求庫 AIOHTTP 基礎入門
小白學 Python 爬蟲(33):爬蟲框架 Scrapy 入門基礎(一)
小白學 Python 爬蟲(34):爬蟲框架 Scrapy 入門基礎(二)
小白學 Python 爬蟲(35):爬蟲框架 Scrapy 入門基礎(三) Selector 選擇器
小白學 Python 爬蟲(36):爬蟲框架 Scrapy 入門基礎(四) Downloader Middleware
小白學 Python 爬蟲(39): JavaScript 渲染服務 Scrapy-Splash 入門
Scrapy 抓取頁面的方式和 Requests 類庫是同樣的,都是直接模擬 HTTP 請求,對於由 JavaScript 動態渲染的頁面就有些顯得無能爲力了。
咱們前面抓取由 JavaScript 動態渲染的頁面是使用 Selenium 對接瀏覽器進行頁面抓取,固然,在 Scrapy 中一樣也能夠對接 Selenium 。
經過這種方案,咱們無需關心一個頁面加載是發送的請求,也無需關注頁面的渲染過程,直接抓取最終結果就行,真正作到了可見便可抓。
首先定一個小目標,前面的文章咱們經過 Selenium 抓取了某東的商品信息,本篇咱們依然使用這個站點,感謝某東爲咱們提供的素材。
請各位同窗確認本身本地已經正確安裝 Scrapy 、 Selenium 以及 Selenium 所須要使用的一些驅動庫,若是還沒有安裝的同窗能夠翻翻前面的文章。
本篇內容仍是新建一個新的 Scrapy 項目,而且命名爲 scrapy_selenium_demo ,命令以下:
scrapy startproject scrapy_selenium_demo
記得找一個本身喜歡的目錄,最好是純英文目錄。
而後新建一個 Spider ,命令以下:
scrapy genspider jd www.jd.com
記得順手修改下 settings.py 中的配置,將 robots.txt 設置爲 False ,不然咱們沒法抓取到相關的商品數據,由於在機器人協議中某東並不容許抓取商品數據,修改以下:
ROBOTSTXT_OBEY = False
第一步仍是咱們將要抓取的數據結構定義到 Item ,代碼以下:
import scrapy class ProductItem(scrapy.Item): collection = 'products' image = scrapy.Field() price = scrapy.Field() name = scrapy.Field() commit = scrapy.Field() shop = scrapy.Field() icons = scrapy.Field()
這裏咱們定義了 6 個字段,和以前的示例徹底相同,而後定一個了 collection ,這個是用於保存進數據的表的名稱。
接下來,是咱們的 Spider 的定義,先初步的定義一個 start_requests() 方法,後續還會有修改,示例以下:
# -*- coding: utf-8 -*- from scrapy import Request, Spider class JdSpider(Spider): name = 'jd' allowed_domains = ['www.jd.com'] start_urls = ['http://www.jd.com/'] def start_requests(self): base_url = 'https://search.jd.com/Search?keyword=iPhone&ev=exbrand_Apple' headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36', 'referer': 'https://www.jd.com/' } for page in range(1, self.settings.get('MAX_PAGE') + 1, 2): url = base_url + '&page=' + str(page) yield Request(url=url, callback=self.parse, headers = headers)
最大的頁碼使用 MAX_PAGE 來表示,一樣的這個配置須要添加至 settings.py 配置文件,以下:
MAX_PAGE = 3
在 start_requests() 中,咱們經過 url 地址拼接的方式,遍歷出來了全部咱們須要訪問的頁面,由於某東的商品頁面的翻頁規則,這裏咱們使用的步長爲 2 。
接下來咱們須要對這些請求進行數據抓取,這裏咱們經過對接 Selenium 來完成。
具體的實現方案是使用 Download Middleware 來完成對接。示例代碼以下:
# -*- coding: utf-8 -*- # Define here the models for your spider middleware # # See documentation in: # https://docs.scrapy.org/en/latest/topics/spider-middleware.html from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from scrapy.http import HtmlResponse from logging import getLogger class SeleniumMiddleware(object): def __init__(self, timeout=None, service_args=[]): self.logger = getLogger(__name__) self.timeout = timeout # Chrome 開啓無窗口模式 chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless') self.driver = webdriver.Chrome(service_args=service_args, chrome_options=chrome_options) self.driver.set_window_size(1400, 700) self.driver.implicitly_wait(self.timeout) self.driver.set_page_load_timeout(self.timeout) self.wait = WebDriverWait(self.driver, self.timeout) def __del__(self): self.driver.close() def process_request(self, request, spider): self.logger.debug('Chrome is Starting') try: page = request.meta.get('page', 1) self.driver.get(request.url) if page > 1: input = self.wait.until( EC.presence_of_element_located((By.XPATH, '//*[@id="J_bottomPage"]/span[2]/input'))) button = self.wait.until( EC.element_to_be_clickable((By.XPATH, '//*[@id="J_bottomPage"]/span[2]/a'))) input.clear() input.send_keys(page) button.click() return HtmlResponse(url=request.url, body=self.driver.page_source, request=request, encoding='utf-8', status=200) except TimeoutException: return HtmlResponse(url=request.url, status=500, request=request) @classmethod def from_crawler(cls, crawler): return cls(timeout=crawler.settings.get('SELENIUM_TIMEOUT'), service_args=crawler.settings.get('CHROME_SERVICE_ARGS'))
寫完 Download Middleware 需在 settings.py 中增長 Download Middleware 的相關配置,以下:
DOWNLOADER_MIDDLEWARES = { 'scrapy_selenium_demo.middlewares.SeleniumMiddleware': 543, }
咱們在 Download Middleware 中得到了 HtmlResponse ,這時須要在 Spider 中進行解析,以下:
def parse(self, response): products = response.css('#J_goodsList .gl-item .gl-i-wrap') for product in products: item = ProductItem() item['image'] = product.css('.p-img a img::attr("src")').extract_first() item['price'] = product.css('.p-price i::text').extract_first() item['name'] = product.css('.p-name em::text').extract_first() item['commit'] = product.css('.p-commit a::text').extract_first() item['shop'] = product.css('.p-shop a::text').extract_first() item['icons'] = product.css('.p-icons .goods-icons::text').extract_first() yield item
咱們增長一個 ITEM_PIPELINES MongoPipeline 將數據保存至 MongoDB ,以下:
import pymongo class MongoPipeline(object): def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls(mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DB') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def process_item(self, item, spider): name = item.__class__.__name__ self.db[name].insert(dict(item)) return item def close_spider(self, spider): self.client.close()
在 settings 中新增相關配置:
ITEM_PIPELINES = { 'scrapy_selenium_demo.pipelines.MongoPipeline': 300, }
至此,咱們就完成主體程序,可使用如下命令運行這隻爬蟲:
scrapy crawl jd
結果小編就不貼了,代碼已上傳代碼倉庫,有興趣的同窗能夠訪問代碼倉庫獲取。
本系列的全部代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便你們取用。
原文出處:https://www.cnblogs.com/babycomeon/p/12194938.html