Python scrapy增量爬取例項及實現過程解析

ckxllf發表於2020-03-06

  這篇文章主要介紹了Python scrapy增量爬取例項及實現過程解析,文中透過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值。

  開始接觸爬蟲的時候還是初學Python的那會,用的還是request、bs4、pandas,再後面接觸scrapy做個一兩個爬蟲,覺得還是框架好,可惜都沒有記錄都忘記了,現在做推薦系統需要爬取一定的文章,所以又把scrapy撿起來。趁著這次機會做一個記錄。

  目錄如下:

  環境

  本地視窗除錯命令

  工程目錄

  xpath選擇器

  一個簡單的增量爬蟲示例

  配置介紹

  環境

  自己的環境下安裝scrapy肯定用anaconda(再次強調anaconda的優越性

  本地視窗除錯與執行

  開發的時候可以利用scrapy自帶的除錯功能進行模擬請求,這樣request、response都會與後面程式碼保持一樣。

  # 測試請求某網站

  scrapy shell URL

  # 設定請求頭

  scrapy shell -s USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" URL

  # 指定爬蟲內容輸出檔案格式(json、csv等

  scrapy crawl SPIDER_NAME -o FILE_NAME.csv

  # 建立爬蟲工程

  scrapy startproject articles # 在當前目錄建立一個scrapy工程

  新工程結構介紹

  # spiders檔案下存放所有爬蟲,item.py格式化資料輸出

  # middlewares.py 設定請求細節(請求頭之類的),pipelines.py為資料輸出的管道,每一個封裝好的item都會經過這裡

  # settings.py 對工程進行全域性設定(存放配置

  ├── articles

  │ ├── articles

  │ │ ├── __init__.py

  │ │ ├── items.py

  │ │ ├── middlewares.py

  │ │ ├── pipelines.py

  │ │ ├── settings.py

  │ │ └── spiders

  │ │ ├── healthy_living.py

  │ │ ├── __init__.py

  │ │ └── people_health.py

  │ └── scrapy.cfg

  ├── README.en.md

  └── README.md

  頁面解析神器——Xpath選擇器

  scrapy自帶xpath選擇器,很方便,簡單介紹一些常用的

  # 全站爬取神器--LinkExtractor,可以自動獲取該標籤下的所有url跟text(因為網站結構大都一個套路

  from scrapy.linkextractors import LinkExtractor

  le = LinkExtractor(restrict_xpaths="//ul[@class='nav2_UL_1 clearFix']")# 返回一個迭代器,透過迴圈(for i in le),可獲取url(i.url) (i.text)

  # 獲取屬性class為所有aa的div標籤內容中的內容

  response.xpath("//div[@class='aa']/text()").extract() # '//'代表獲取所有,'/'代表獲取第一個,類似的可以找屬性為ul的其它標籤

  # 獲取內容包含“下一頁”的所有a標籤中包含的連結(提取下一頁連結神器

  response.xpath("//a[contains(text(),'下一頁')]/@href").extract()

  一個簡單的增量爬取示例

  這裡增量爬取的思想很簡單:目標網站的資料都是按照時間排列的,所以在對某個連線進行request之前,先查詢資料庫中有沒有這條資料,如果有,就停止爬蟲,如果沒有發起請求

  class HealthyLiving(scrapy.Spider):

  # 一定要一個全域性唯一的爬蟲名稱,命令列啟動的時候需要指定該名稱

  name = "healthy_living"

  # 指定爬蟲入口,scrapy支援多入口,所以一定是lis形式

  start_urls = [']

  '''

  抓取大類標籤入口

  '''

  def parse(self, response):

  le = LinkExtractor(restrict_xpaths="//ul[@class='nav2_UL_1 clearFix']")

  for link in le.extract_links(response)[1:-1]:

  tag = link.text

  # 將這一級提取到的資訊,透過請求頭傳遞給下一級(這裡是為了給資料打標籤

  meta = {"tag": tag}

  # 依次解析每一個連結,並傳遞到下一級進行繼續爬取

  yield scrapy.Request(link.url, callback=self.parse_articles, meta=meta)

  '''

  抓取頁面內的文章連結及下一頁連結

  '''

  def parse_articles(self, response):

  # 接收上一級傳遞的資訊

  meta = response.meta

  article_links = response.xpath("//div[@class='txt']/h4/a/@href").extract()

  for link in article_links:

  res = self.collection.find_one({"article_url": link}, {"article_url": 1})

  full_meta = dict(meta)

  # 將文章連結傳入下一級

  full_meta.update({"article_url": link})

  if res is None:

  yield scrapy.Request(link, callback=self.parse_article, meta=full_meta)

  else:

  return

  next_page = response.xpath("//div[@class='page']//a[contains(text(),'»')]/@href").extract()[0]

  if next_page:

  yield scrapy.Request(next_page, callback=self.parse_articles, meta=meta)

  # 最後解析頁面,並輸出

  def parse_article(self, response):

  # 從item.py中匯入資料封裝格式

  article_item = ArticlesItem()

  meta = response.meta

  # 利用xpath提取頁面資訊並封裝成item

  try:

  article_item["tag"] = ""

  # ... 省略

  finally:

  yield article_item

  工程配置介紹

  設定請求頭、配置資料庫

  # 設定請求頭,在middlewares.py中設定,在settings.py中啟用

  class RandomUA(object):

  user_agents = [

  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit"

  "/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",

  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11", 鄭州婦科醫院哪家好

  "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit"

  "/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16"

  ]

  def process_request(self, request, spider):

  request.headers["User-Agent"] = random.choice(self.user_agents)

  # 設定資料入庫處理,在pipeline.py進行配置,在settings.py進行啟用

  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):

  print("開始爬取", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

  self.client = pymongo.MongoClient(self.mongo_uri)

  self.db = self.client[self.mongo_db]

  def process_item(self, item, spider):

  data = self.db[item.collection].find_one({"title": item["title"], "date": item["date"]})

  if data is None:

  self.db[item.collection].insert(dict(item))

  # else:

  # self.close_spider(self, spider)

  return item

  def close_spider(self, spider):

  print("爬取結束", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

  self.client.close()[新增連結描述](https://jq.qq.com/?_wv=1027&k=5ipV5It)

  # 在settings.py啟動:請求頭的修改,資料庫的配置

  DOWNLOADER_MIDDLEWARES = {

  # 'articles.middlewares.ArticlesDownloaderMiddleware': 543,

  'articles.middlewares.RandomUA': 543,# 543代表優先順序,數字越低優先順序越高

  }

  ITEM_PIPELINES = {

  'articles.pipelines.MongoPipeline': 300,

  }

  # 一些其它配置

  ROBOTSTXT_OBEY = True # 是否遵守網站的robot協議

  FEED_EXPORT_ENCODING = 'utf-8' # 指定資料輸出的編碼格式

  ## 資料庫配置

  MONGO_URI = ''

  MONGO_DB = ''

  MONGO_PORT = 27017

  MONGO_COLLECTION = ''


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2678794/,如需轉載,請註明出處,否則將追究法律責任。

相關文章