Scrapy爬虫框架,scrapy+selenium

  Scrapy爬虫框架,scrapy+selenium

  本文主要介绍Scrapy integration selenium和scarpy爬虫框架的综合说明。有需要的朋友可以借鉴一下,希望能有所帮助。祝大家进步很大,早日升职加薪。

  00-1010一、建筑概论二。安装、创建和启动介绍。配置文件目录介绍。数据的抓取和分析五、保存到文件的数据的持久性保存到redis保存到MongoDB保存到mysql VI。动作链,滑动验证码VII。提高爬行效率。假用户代理池IX。中间件配置流程_异常错误处理流程_请求加代理、添加cookie等。十、硒XI的整合。指纹和Bloom filter实现增量抓取URL指纹Bloom filter XII。分布式爬虫XIII。爬虫框架全站爬行用例

  

目录

  Scrapy是一个开源的协作框架,最初是为页面抓取(更确切地说是web抓取)而设计的。使用它,我们可以以快速、简单和可扩展的方式从网站中提取所需的数据。不过目前Scrapy已经有了广泛的应用,比如数据挖掘、监控、自动化测试等领域。它还可以用于获取API(例如,Amazon Associates Web Services)或通用网络爬虫返回的数据。

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

  IO多路复用

  #工程师(EGINE)(总经理)

  该引擎负责控制系统所有组件之间的数据流,并在特定操作发生时触发事件。有关更多信息,请参见上面的数据流部分。

  #调度程序(调度程序)

  它用于接受引擎发送的请求,将其推入队列,并在引擎再次请求时返回。它可以被认为是一个URL的优先级队列,它决定了下一个要抓取的URL并删除重复的URL。

  #下载者(下载者)

  用于下载网页内容并返回给EGINE,下载器基于twisted,一种高效的异步模型。

  #爬虫(蜘蛛)

  蜘蛛是开发人员定义的类,用于解析响应、提取项目或发送新请求。

  #项目管道(项目管道)

  项目提取出来后,负责处理,主要包括清理、验证、持久化(比如保存到数据库)等操作。

  # 2中间件

  -爬虫中间件

  -下载中间件(最常用的,header,proxy,cookie和selenium集成)

  

一、架构介绍

  # 1框架不是一个模块。

  # 2被称为爬行动物世界的django(你会发现它和django的很多地方一样)

  # 3安装

  -mac,linux平台:pip3安装scrapy

  -windows平台:pip3安装scrapy(大多数人可以)

  -如果失败:

  1.pip3 install wheel #安装后,可以通过wheel文件安装软件,该文件在https://www.lfd.uci.edu/~gohlke/pythonlibs,官网

  3、pip3安装lxml

  4、pip3安装pyopenssl

  5.下载并安装py win32:https://sourceforge.net/projects/pywin32/fil

  es/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)

  

  

  

  

四、爬取数据,并解析

  

# 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]

   title = div.select(h3)[0].text

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

   title = scrapy.Field()

   content_summary = scrapy.Field()

   content = scrapy.Field()

  

  pipelines.py 数据持久化文件

  

# -*- coding: utf-8 -*-

  # Define your item pipelines here

  # Dont 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的资料请关注盛行IT软件开发工作室其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: