ITPub博客

首页 > 应用开发 > Python > Python scrapy增量爬取实例及实现过程解析

Python scrapy增量爬取实例及实现过程解析

原创 Python 作者:ckxllf 时间:2020-03-06 10:33:18 0 删除 编辑

  这篇文章主要介绍了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 = ['http://www.jkb.com.cn/healthyLiving/']

  '''

  抓取大类标签入口

  '''

  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", 郑州妇科医院哪家好 http://mobile.120zzzy.com/

  "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博客 ” ,链接:https://blog.itpub.net/69945560/viewspace-2678794/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-16

  • 博文量
    204
  • 访问量
    262652