脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - Scrapy爬虫框架集成selenium及全面详细讲解

Scrapy爬虫框架集成selenium及全面详细讲解

2022-11-28 09:55Jeff的技术栈 Python

这篇文章主要为大家介绍了Scrapy集成selenium,以及scarpy爬虫框架全面讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪

一、架构介绍

Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速、简单、可扩展的方式从网站中提取所需的数据。但目前Scrapy的用途十分广泛,可用于如数据挖掘、监测和自动化测试等领域,也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。整体架构大致如下

IO多路复用

Scrapy爬虫框架集成selenium及全面详细讲解

# 引擎(EGINE)(大总管)

引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。有关详细信息,请参见上面的数据流部分。

# 调度器(SCHEDULER)

用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

# 下载器(DOWLOADER)

用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的

# 爬虫(SPIDERS)

SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求

# 项目管道(ITEM PIPLINES)

在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作

# 两个中间件

-爬虫中间件

-下载中间件(用的最多,加头,加代理,加cookie,集成selenium)

 

二、安装创建和启动

# 1 框架 不是 模块
# 2 号称爬虫界的django(你会发现,跟django很多地方一样)
# 3 安装
	-mac,linux平台:pip3 install scrapy
-windows平台:pip3 install scrapy(大部分人可以)
	- 如果失败:
    1、pip3 install wheel #安装后,便支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
    3、pip3 install lxml
    4、pip3 install pyopenssl
    5、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
    6、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
    7、执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl
    8、pip3 install scrapy
# 4 在script文件夹下会有scrapy.exe可执行文件
	-创建scrapy项目:scrapy startproject 项目名   (django创建项目)
	-创建爬虫:scrapy genspider 爬虫名 要爬取的网站地址   # 可以创建多个爬虫
# 5 命令启动爬虫
		-scrapy crawl 爬虫名字
		-scrapy crawl 爬虫名字 --nolog   # 没有日志输出启动
# 6 文件执行爬虫(推荐使用)
	-在项目路径下创建一个main.py,右键执行即可
	from scrapy.cmdline import execute
  # execute(['scrapy','crawl','chouti','--nolog'])  # 没有设置日志级别
  execute(['scrapy','crawl','chouti'])			  # 设置了日志级别

 

三、配置文件目录介绍

-crawl_chouti   # 项目名
-crawl_chouti # 跟项目一个名,文件夹
  -spiders    # spiders:放着爬虫  genspider生成的爬虫,都放在这下面
  	-__init__.py
    -chouti.py # 抽屉爬虫
    -cnblogs.py # cnblogs 爬虫
  -items.py     # 对比django中的models.py文件 ,写一个个的模型类
  -middlewares.py  # 中间件(爬虫中间件,下载中间件),中间件写在这
  -pipelines.py   # 写持久化的地方(持久化到文件,mysql,redis,mongodb)
  -settings.py    # 配置文件
-scrapy.cfg       # 不用关注,上线相关的
# 配置文件settings.py
ROBOTSTXT_OBEY = False   # 是否遵循爬虫协议,强行运行
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'    # 请求头中的ua,去浏览器复制,或者用ua池拿
LOG_LEVEL='ERROR' # 这样配置,程序错误信息才会打印,
	#启动爬虫直接 scrapy crawl 爬虫名   就没有日志输出
	# scrapy crawl 爬虫名 --nolog  # 配置了就不需要这样启动了
# 爬虫文件
class ChoutiSpider(scrapy.Spider):
  name = 'chouti'   # 爬虫名字
  allowed_domains = ['https://dig.chouti.com/']  # 允许爬取的域,想要多爬就注释掉
  start_urls = ['https://dig.chouti.com/']   # 起始爬取的位置,爬虫一启动,会先向它发请求
  def parse(self, response):  # 解析,请求回来,自动执行parser,在这个方法中做解析
      print('---------------------------',response)

Scrapy爬虫框架集成selenium及全面详细讲解

 

四、爬取数据,并解析

# 1 解析,可以使用bs4解析
from bs4 import BeautifulSoup
soup=BeautifulSoup(response.text,'lxml')
soup.find_all()  # bs4解析
soup.select()  # css解析
# 2 内置的解析器
response.css  
response.xpath
# 内置解析 
# 所有用css或者xpath选择出来的都放在列表中
# 取第一个:extract_first()
# 取出所有extract()
# css选择器取文本和属性:
  # .link-title::text  # 取文本,数据都在data中
  # .link-title::attr(href)   # 取属性,数据都在data中
# xpath选择器取文本和属性
  # .//a[contains(@class,"link-title")/text()]
  #.//a[contains(@class,"link-title")/@href]
# 内置css选择期,取所有
div_list = response.css('.link-con .link-item')
for div in div_list:
  content = div.css('.link-title').extract()
  print(content)

 

五、数据持久化

# 方式一(不推荐)
-1 parser解析函数,return 列表,列表套字典
  # 命令   (支持:('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')
  # 数据到aa.json文件中
-2 scrapy crawl chouti -o aa.json   
# 代码:
lis = []
for div in div_list:
  content = div.select('.link-title')[0].text
  lis.append({'title':content})
  return lis
# 方式二 pipline的方式(管道)
 -1 在items.py中创建模型类
 -2 在爬虫中chouti.py,引入,把解析的数据放到item对象中(要用中括号)
 -3 yield item对象
 -4 配置文件配置管道
     ITEM_PIPELINES = {
      # 数字表示优先级(数字越小,优先级越大)
     'crawl_chouti.pipelines.CrawlChoutiPipeline': 300,
     'crawl_chouti.pipelines.CrawlChoutiRedisPipeline': 301,
  	}
-5 pipline.py中写持久化的类
      spider_open  # 方法,一开始就打开文件
      process_item # 方法,写入文件
      spider_close # 方法,关闭文件

保存到文件

# choutiaa.py 爬虫文件
import scrapy
from chouti.items import ChoutiItem  # 导入模型类
class ChoutiaaSpider(scrapy.Spider):
  name = 'choutiaa'
  # allowed_domains = ['https://dig.chouti.com/']   # 允许爬取的域
  start_urls = ['https://dig.chouti.com//']   # 起始爬取位置
  # 解析,请求回来,自动执行parse,在这个方法中解析
  def parse(self, response):
      print('----------------',response)
      from bs4 import BeautifulSoup
      soup = BeautifulSoup(response.text,'lxml')
      div_list = soup.select('.link-con .link-item')
      for div in div_list:
          content = div.select('.link-title')[0].text
          href = div.select('.link-title')[0].attrs['href']
          item = ChoutiItem()  # 生成模型对象
          item['content'] = content  # 添加值
          item['href'] = href
          yield item  # 必须用yield  	
# items.py 模型类文件
import scrapy
class ChoutiItem(scrapy.Item):
  content = scrapy.Field()
  href = scrapy.Field()
# pipelines.py 数据持久化文件
class ChoutiPipeline(object):
  def open_spider(self, spider):
      # 一开始就打开文件
      self.f = open('a.txt', 'w', encoding='utf-8')
  def process_item(self, item, spider):
      # print(item)
      # 写入文件的操作
      self.f.write(item['content'])
      self.f.write(item['href'])
      self.f.write('\n')
      return item
  def close_spider(self, spider):
      # 写入完毕,最后关闭文件
      self.f.close()
# setting.py
ITEM_PIPELINES = {
  # 数字表示优先级,越小优先级越高
 'chouti.pipelines.ChoutiPipeline': 300,
 'chouti.pipelines.ChoutiRedisPipeline': 301,
}

保存到redis

# settings.ps
ITEM_PIPELINES = {
  # 数字表示优先级,越小优先级越高
 'chouti.pipelines.ChoutiPipeline': 300,
 'chouti.pipelines.ChoutiRedisPipeline': 301,
}
# pipelines.py
# 保存到redis
from redis import Redis
class ChoutiRedisPipeline(object):
  def open_spider(self, spider):
      # 不写参数就用默认配置
      self.conn = Redis(password='123')  # 一开始就拿到redis对象
  def process_item(self, item, spider):
      print(item)
      import json
      s = json.dumps({'content': item['content'], 'href': item['href']})
      self.conn.hset('choudi_article', item['id'], s)
      return item
  def close_spider(self, spoder):
      pass
      # self.conn.close()
# chouti.py
import scrapy
from chouti.items import ChoutiItem  # 导入模型类
class ChoutiaaSpider(scrapy.Spider):
  name = 'choutiaa'
  # allowed_domains = ['https://dig.chouti.com/']   # 允许爬取的域
  start_urls = ['https://dig.chouti.com//']   # 起始爬取位置
  # 解析,请求回来,自动执行parse,在这个方法中解析
  def parse(self, response):
      print('----------------',response)
      from bs4 import BeautifulSoup
      soup = BeautifulSoup(response.text,'lxml')
      div_list = soup.select('.link-con .link-item')
      for div in div_list:
          content = div.select('.link-title')[0].text
          href = div.select('.link-title')[0].attrs['href']
          id = div.attrs['data-id']
          item = ChoutiItem()  # 生成模型对象
          item['content'] = content  # 添加值
          item['href'] = href
          item['id'] = id
          yield item  # 必须用yield

保存到MongoDB

#一.下载并安装mongodb
pip install pymongo
#二、在settings中打开PIPELINES并把数据库相应配置写入
ITEM_PIPELINES = {
  '<spider_name>.pipelines.ChoutiPipeline': 300,
}
MONGODB_HOST = '127.0.0.1'
# 端口号,默认27017
MONGODB_PORT = 27017
# 设置数据库名称
MONGODB_DBNAME = 'Chouti'
# 存放本数据的表名称
MONGODB_DOCNAME = 'Chouti'
#三.修改pipelines文件
import pymongo
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
class DouluodaluPipeline(object):
  def __init__(self):
      # 获取setting主机名、端口号和数据库名称
      host = settings['MONGODB_HOST']
      port = settings['MONGODB_PORT']
      dbname = settings['MONGODB_DBNAME']
      # 创建数据库连接
      client = pymongo.MongoClient(host=host,port=port)
      # 指向指定数据库
      mdb = client[dbname]
      # 获取数据库里面存放数据的表名
      self.post = mdb[settings['MONGODB_DOCNAME']]
  def process_item(self, item, spider):
      data = dict(item)
      # 向指定的表里添加数据
      self.post.insert(data)
      return item

保存到mysql

import pymysql.cursors
class MySQLPipeline(object):
  def __init__(self):
      # 连接数据库
      self.connect = pymysql.connect(
          host='127.0.0.1',  # 数据库地址
          port=3306,  # 数据库端口
          db='scrapyMysql',  # 数据库名
          user='root',  # 数据库用户名
          passwd='root',  # 数据库密码
          charset='utf8',  # 编码方式
          use_unicode=True)
      # 通过cursor执行增删查改
      self.cursor = self.connect.cursor()
  def process_item(self, item, spider):
      self.cursor.execute(
          """insert into mingyan(tag, cont)
          value (%s, %s)""",  # 纯属python操作mysql知识,不熟悉请恶补
          (item['tag'],  # item里面定义的字段和表字段对应
           item['cont'],))
      # 提交sql语句
      self.connect.commit()
      return item  # 必须实现返回

 

六、动作链,控制滑动的验证码

from selenium import webdriver
from selenium.webdriver import ActionChains
import time
bro=webdriver.Chrome(executable_path='./chromedriver')
bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
bro.implicitly_wait(10)
#切换frame(很少)
bro.switch_to.frame('iframeResult')
div=bro.find_element_by_xpath('//*[@id="draggable"]')
# 1 生成一个动作练对象
action=ActionChains(bro)
# 2 点击并夯住某个控件
action.click_and_hold(div)
# 3 移动(三种方式)
# action.move_by_offset() # 通过坐标(x,y)
# action.move_to_element() # 到另一个标签
# action.move_to_element_with_offset() # 到另一个标签,再偏移一部分
for i in range(5):
  action.move_by_offset(10,10)
# 4 真正的移动
action.perform()

# 5 释放控件(松开鼠标)
action.release()

async def login():
  for res in setting.user:
      try:
          username = res[0]
          password = res[1]
          # headless参数设为False,则变成有头模式
          browser = await launch(
              {'headless': False}
          )
          # 打开一个页面
          page = await browser.newPage()
          await page.setViewport(viewport={'width': 1280, 'height': 800})
          res = await page.goto('https://login.taobao.com/', options={'timeout': 10000})
          await page.type('#fm-login-id', username)
          await page.type('#fm-login-password', password)
          await page.waitFor(1000)  # 等待时间
          slider = await page.querySelector('#nc_1_n1z')  # 是否有滑块
          if slider:
              try:
                  print('有滑块')
                  await page.hover('#nc_1_n1z')  # 不同场景的验证码模块能名字不同。
                  await page.mouse.down()
                  await page.mouse.move(2000, 0, {'delay': random.randint(1000, 2000)})
                  await page.mouse.up()
              except Exception as e:
                  print(e)
                  input('验证失败,人工登录:')
          else:
              print('没有滑块')
          await page.click("#login-form > div.fm-btn > button")  # 点击登录
          input('进入登录成功页面后,按回车:')
          return page
      except Exception as e:
          continue

 

七、提高爬取效率

- 在配置文件中进行相关的配置即可:(默认还有一套setting)
#1 增加并发:
默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。
#2 提高日志级别:
在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO'
# 3 禁止cookie:
如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False
# 4禁止重试:
对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False
# 5 减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s

 

八、fake-useragent池

# pip3 install fake-useragent
from fake_useragent import UserAgent
ua = UserAgent(verify_ssl=False)
print(ua.random)  # 随机获取一个UserAgent

 

九、中间件配置

#大中间件:下载中间件,爬虫中间件
# 1 写在middlewares.py中(名字随便命名)
# 2 配置生效()
# 爬虫中间件
SPIDER_MIDDLEWARES = {
 'cnblogs_crawl.middlewares.CnblogsCrawlSpiderMiddleware': 543,
}
# 下载中间件
DOWNLOADER_MIDDLEWARES = {
 'cnblogs_crawl.middlewares.CnblogsCrawlDownloaderMiddleware': 543,
}
# 下载中间件
# 在cnblogs_crawl.middlewares.CnblogsCrawlDownloaderMiddleware中有五个方法
# 请求出去的时候
def process_request(self, request, spider)
	# Must either:
  # - return None:   # 返回none继续处理,进入下一个中间件
  # - return Response: 当次请求结束,把Response丢给引擎处理(可以自己爬,包装成Response)
  # - return Request : 相当于把Request重新给了引擎,引擎再去做调度
  # - 抛异常:执行process_exception
# 请求回来的时候
def process_response(self, request, response, spider)
	# - return a Response object :继续处理当次Response,继续走后续的中间件
  # - return a Request object:重新给引擎做调度
	# - 抛异常:执行process_exception
# 请求异常的时候
def process_exception(self, request, exception, spider)
	# - return None: 不处理异常,继续丢给下面
  # - return a Response:停止异常处理,不丢给下面。给引擎。Response给爬虫分析数据
  # - return a Request:停止异常处理,不丢给下面。给引擎。Request重新调度
  

process_exception 错误处理

class CnblogsSpider(scrapy.Spider):
  name = 'cnblogs4'
  allowed_domains = ['www.cnblogs.com']
  start_urls = ['http://wwwsadasd.cnblogs.com/']   # 错误的网址,报错走异常处理
# 走异常处理,重新返回一个正确的Request对象
def process_exception(self, request, exception, spider):
  print(request.url)  # http://wwwsadasd.cnblogs.com/
  from scrapy.http import Request
  return Request('http://www.cnblogs.com/',callback=spider.parser_detail)

process_request 加代理,加cookie等

    def process_request(self, request, spider):
      # 1 加cookie(request.cookies就是访问该网站的cookie)
      print(request.cookies)
      request.cookies={'name':"jeff",'age':18}  # 从你的cookie池中取出来的,  字典
      print(request.cookies)
      # 2 加代理
      request.meta['proxy']=self.get_proxy()   # 从代理池中获取一个
      print(request.meta['proxy'])
      # 3 修改ua
      from fake_useragent import UserAgent   # ua模块,随机获取一个
      ua = UserAgent(verify_ssl=False)
      request.headers['User-Agent']=ua.random
      print(request.headers)
# 代理池
def get_proxy(self):
  import requests
  ret=requests.get('http://0.0.0.0:5010/get').json()['proxy']
  print(ret)
  return ret
      return None

 

十、集成selenium

#可在两个地方集成。
#1.process_request(请求出去的时候)  # 推荐写这里,少请求一次。直接集成封装
#2.process_response(请求回来的时候) # 不推荐,因为夺走了一次请求,回来再集成封装
# 方案一:缺点很大。每次一请求都要打开一个bro浏览器
def process_request(self, request, spider):
  from selenium import webdriver
  from scrapy.http import HtmlResponse
  bro = webdriver.Chrome(executable_path='../chromedriver')
  bro.get(request.url)
  text = bro.page_source
  response = HtmlResponse(url=request.url, body=text.encode('utf-8'), status=200)
  return response
# 方案二:改进为一开始就打开一个bro浏览器,后面都用这一个bro
class CnblogsSpider(scrapy.Spider):
  name = 'cnblogs'
  from selenium import webdriver
  # 在爬虫一开始就打开bro对象
  bro = webdriver.Chrome(executable_path='../chromedriver')  
  # 在爬虫中新添加的方法:关闭bro
  def close(spider, reason):
  	spider.bro.close()  # 爬虫结束关闭
# 中间件中
def process_request(self, request, spider):
  from scrapy.http import HtmlResponse
  spider.bro.get(request.url)  # 每个请求使用一个bro
  text = spider.bro.page_source
  response = HtmlResponse(url=request.url, body=text.encode('utf-8'), status=200)
  return response

 

十一、指纹和布隆过滤器实现增量爬取

什么是增量爬取?

-增量爬取(100链接,150个链接)

  • -已经爬过的,放到某个位置(mysql,redis中:集合)
  • -如果用默认的,爬过的地址,放在内存中,只要项目一重启,就没了,它也不知道我爬过那个了,所以要自己重写去重方案

-你写的去重方案,占得内存空间更小

-bitmap方案

-BloomFilter布隆过滤器

网址指纹

# 一、网址指纹
from scrapy.http import Request
from scrapy.utils.request import request_fingerprint
# 这种网址是一个
request1 = Request(url='https://www.baidu.com/s?name=jeff&age=18')
request2 = Request(url='https://www.baidu.com/s?age=18&name=jeff')
ret1=request_fingerprint(requests1)
ret2=request_fingerprint(requests2)
print(ret1) # 6961985868392ae44c15ada494ddeda856cf75fc
print(ret2) # 6961985868392ae44c15ada494ddeda856cf75fc

布隆过滤器

# 安装
# 1.需要先安装bitarray  #下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
# 2.下载好之后 pip3 install 文件拖进去
# 3.pip3 install pybloom_live
#ScalableBloomFilter 可以自动扩容
from pybloom_live import ScalableBloomFilter
bloom = ScalableBloomFilter(initial_capacity=100, error_rate=0.001, mode=ScalableBloomFilter.LARGE_SET_GROWTH)
url = "https://www.baidu.com/s?name=jeff&age=18"
url2 = "https://www.baidu.com/s?age=18&name=jeff"
bloom.add(url)
print(url in bloom)
print(url2 in bloom)

使用一:添加网址(不推荐)

#BloomFilter 是定长的
from pybloom_live import BloomFilter
bf = BloomFilter(capacity=1000)
url='www.baidu.com'
bf.add(url)
print(url in bf)
print("www.liuqingzheng.top" in bf)

使用二:添加网址指纹(推荐),配合指纹使用

from scrapy.http import Request
from scrapy.utils.request import request_fingerprint
from pybloom_live import BloomFilter
request1 = Request(url='https://www.baidu.com/s?name=jeff&age=18')
request2 = Request(url='https://www.baidu.com/s?age=18&name=jeff')
ret1=request_fingerprint(request1)
ret2=request_fingerprint(request2)
print(ret1) # 6961985868392ae44c15ada494ddeda856cf75fc
print(ret2) # 6961985868392ae44c15ada494ddeda856cf75fc
bf = BloomFilter(capacity=1000) # 1000容量
bf.add(ret2)
if ret1 in bf:
  print('已经爬过此网站,True')
else:
  bf.add(ret1)  # 添加
  print('还没有爬过此网站,返回false')

 

十二、分布式爬虫

github地址:https://github.com/rmax/scrapy-redis
# 1 安装pip3 install scrapy-redis
# 源码部分,不到1000行,
# 1 原来的爬虫继承
from scrapy_redis.spiders import RedisSpider
class CnblogsSpider(RedisSpider):
	#start_urls = ['http://www.cnblogs.com/']
  redis_key = 'myspider:start_urls'  # 起始地址为空,在redis中拿
# 2 在setting中配置
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
ITEM_PIPELINES = { 
   'chouti.pipelines.Pipeline': 300,               # 用自己的入库类,比如mysql中
   # 'scrapy_redis.pipelines.RedisPipeline': 300  # 存在别人写好的redis入库类
}
REDIS_PARAMS  = {'password':'123'}   # 如果redis有密码就配置
#其他更多配置见github
# 3 多台机器上启动scrapy
# 4 向reids中发送起始url
redis-cli lpush myspider:start_urls https://www.cnblogs.com

 

十三、爬虫框架全站爬取使用案例

可以同时启动两个爬虫,爬不同的网站。但是建议爬不同的网站新建项目

chouti.py 爬虫:

import scrapy
from chouti.items import ChoutiItem  # 导入模型类
class ChoutiaaSpider(scrapy.Spider):
  name = 'choutiaa'
  # allowed_domains = ['https://dig.chouti.com/']   # 允许爬取的域
  start_urls = ['https://dig.chouti.com//']   # 起始爬取位置
  # 解析,请求回来,自动执行parse,在这个方法中解析
  def parse(self, response):
      print('----------------',response)
      from bs4 import BeautifulSoup
      soup = BeautifulSoup(response.text,'lxml')
      div_list = soup.select('.link-con .link-item')
      for div in div_list:
          content = div.select('.link-title')[0].text
          href = div.select('.link-title')[0].attrs['href']
          id = div.attrs['data-id']
          item = ChoutiItem()  # 生成模型对象
          item['content'] = content  # 添加值
          item['href'] = href
          item['id'] = id
          yield item  # 必须用yield

cnblogs.py 爬虫:

# -*- coding: utf-8 -*-
import scrapy
from bs4 import BeautifulSoup
from chouti.items import CnblogsItem  # 导入模型类
from scrapy.http import Request
class CnblogsSpider(scrapy.Spider):
  name = 'cnblogs'
  start_urls = ['https://www.cnblogs.com/']
  def parse(self, response):
      print('------', response)
      soup = BeautifulSoup(response.text, 'lxml')
      div_list = soup.select('#post_list .post_item')
      for div in div_list:
          author = div.select('.post_item_foot a')[0].text
          content_url = div.select('h3 a')[0].attrs['href']
          content_summary = div.select('p')[0].text
          item = CnblogsItem()
          item['author'] = author
          item['content_url'] = content_url
          item['title'] = title
          item['content_summary'] = content_summary
          # print(f'''
          # 作者:{author}
          # 文章地址:{content_url}
          # 标题:{title}
          # 文章内容:{content_summary}
          # ''')            
          # 继续往深一层爬取,传递给content_parse
          yield Request(content_url, callback=self.content_parse, meta={'item': item})
      # 获取下一页的标签网址
      next = soup.select('#paging_block > div > a:nth-last-child(1)')[0].attrs['href']
      next = 'https://www.cnblogs.com/'+next
      yield Request(next)   # 继续爬取下一页
  def content_parse(self, response):
      item = response.meta.get('item')
      content = response.css('#cnblogs_post_body').extract_first()
      if not content:
          content = response.css('content').extract_first()
      item['content'] = content
      # print(item)
      yield item

items.py 模型类:

# -*- coding: utf-8 -*-
# Define here the models for your scraped items
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ChoutiItem(scrapy.Item):
  content = scrapy.Field()
  href = scrapy.Field()
  id = scrapy.Field()
class CnblogsItem(scrapy.Item):
  author = scrapy.Field()
  content_url = scrapy.Field()
  content_summary = scrapy.Field()
  content = scrapy.Field()

pipelines.py 数据持久化文件

# -*- coding: utf-8 -*-
# Define your item pipelines here
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# 保存到文件
class Pipeline(object):
  def open_spider(self, spider):
      # choutiaa爬虫入库前
      if spider.name == 'choutiaa':
          # 一开始就打开文件
          self.f = open('a.txt', 'w', encoding='utf-8')
      # cnblog爬虫入库前
      elif spider.name == 'cnblogs':
          import pymysql
          self.conn = pymysql.Connect(host='127.0.0.1', port=3306, db='cnblogs', user='root', password="123",autocommit=True)
  def process_item(self, item, spider):
      # choutiaa爬虫入库中
      if spider.name == 'choutiaa':
          # 写入文件的操作
          self.f.write(item['content'])
          self.f.write(item['href'])
          self.f.write(item['id'])
          self.f.write('\n')
          return item
      # cnblog爬虫入库中
      elif spider.name == 'cnblogs':
          print('cnblogs入库中')
          curser = self.conn.cursor()
          sql = 'insert into article (author,content_url,title,content_summary,content) values (%s,%s,%s,%s,%s)'
          curser.execute(sql, (
          item['author'], item['content_url'], item['title'], item['content_summary'], item['content']))
  def close_spider(self, spider):
      # choutiaa爬虫入库结束
      if spider.name == 'choutiaa':
          # 写入完毕,最后关闭文件
          self.f.close()
      # cnblog爬虫入库结束
      elif spider.name == 'cnblogs':
          print('cnblogs入库完毕')
          self.conn.close()

main.py

from scrapy.cmdline import execute
# execute(['scrapy','crawl','choutiaa'])
execute(['scrapy','crawl','cnblogs'])

以上就是scarpy爬虫框架集成selenium及详细讲解的详细内容,更多关于scarpy爬虫框架结构集成selenium的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/guyouyin123/p/12714455.html

延伸 · 阅读

精彩推荐
  • Python详解pandas获取Dataframe元素值的几种方法

    详解pandas获取Dataframe元素值的几种方法

    这篇文章主要介绍了详解pandas获取Dataframe元素值的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    K.I.O54592020-06-15
  • PythonPython生成密码库功能示例

    Python生成密码库功能示例

    这篇文章主要介绍了Python生成密码库功能,涉及Python基于随机字符串实现的生成密码功能相关操作技巧,需要的朋友可以参考下...

    那片依然海4132020-11-11
  • Pythonopencv canny边缘检测算法详解

    opencv canny边缘检测算法详解

    本文主要介绍了opencv canny边缘检测算法详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    liu_jie_bin9292022-11-03
  • Pythonpython安装教程

    python安装教程

    这篇文章主要为大家详细介绍了python安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    freezing111512242021-01-18
  • Python如何用Python进行时间序列分解和预测

    如何用Python进行时间序列分解和预测

    这篇文章主要介绍了如何用Python进行时间序列分解和预测,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下...

    酸菜鱼编程9912021-09-10
  • PythonPython打包方法Pyinstaller的使用

    Python打包方法Pyinstaller的使用

    在我们完成一个Python项目或一个程序时,希望将Python的py文件打包成在Windows系统下直接可以运行的exe程序。这篇文章主要介绍了Python打包方法Pyinstaller的使...

    晴空行12812021-04-06
  • Python想学python 这5本书籍你必看!

    想学python 这5本书籍你必看!

    想学python,这5本书籍你必看!本文为大家推荐了学习python的5本书籍,5本经典书籍,感兴趣的小伙伴们可以参考一下...

    娇兮心有之8912021-04-28
  • Python基于PyQt4和PySide实现输入对话框效果

    基于PyQt4和PySide实现输入对话框效果

    这篇文章主要为大家详细介绍了基于PyQt4和PySide实现输入对话框效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    网海水手7422021-06-03