您现在的位置是:首页 > 技术教程 正文

Scrapy和Selenium整合(一文搞定)

admin 阅读: 2024-03-25
后台-插件-广告管理-内容页头部广告(手机)

文章目录

  • 前言
  • 一、开始准备
    • 1. 包管理和安装chrome驱动
    • 2. 爬虫项目的创建(举个栗子)
    • 3. setting.py的配置
  • 二、代码演示
    • 1. 主爬虫程序
    • 2. 中间件的配置
    • 3. 定义item对象
    • 4. 定义管道
  • 总结


前言

scrapy和selenium的整合使用
先定个小目标实现万物皆可爬!我们是用scrapy框架来快速爬取页面上的数据,它是自带并发的,速度是可以的。但是一些ajax异步的请求我们不能这么爬取。我们要视同selenium来进行lazy loading,也就是懒加载,渲染到页面加载数据。


一、开始准备

爬取流程图

1. 包管理和安装chrome驱动

首先你要安装以下包:

pip install scrapy pip install selenium == 3.0.0 pip install pymysql pip install bs4
  • 1
  • 2
  • 3
  • 4
  • selenium新版本有bug,用3.0的版本。
  • chrome驱动的exe执行文件,放到你项目的根目录即可。下载地址:驱动

2. 爬虫项目的创建(举个栗子)

  1. 创建项目
scrapy startproject cnki
  • 1
  1. 您爬取的目标网站
scrapy genspider cnki https://www.cnki.net
  • 1
  1. 运行爬虫
# 运行不导出(一般在pipelines做导出操作) scrapy crawl cnki # 针对不同的选择可以导出为xlsx、json等格式文件 scrapy crawl demo -o demo.csv
  • 1
  • 2
  • 3
  • 4

3. setting.py的配置

  1. 配置数据源,如下:
DB_HOST = 'localhost' DB_PORT = 3306 DB_USER = 'root' DB_PASSWORD ='123456' DB_DATABASE = 'spider'
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 防止打印log日志信息
LOG_LEVEL = 'WARNING'
  • 1
  1. 配置USER_AGENT(浏览器控制台找一个)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36
  • 1
  1. 配置DEFAULT_REQUEST_HEADERS(浏览器控制台找一个)
{ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', }
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 随机延迟
DOWNLOAD_DELAY = 3 RANDOMIZE_DOWNLOAD_DELAY=True
  • 1
  • 2
  1. 中间件权重配置(这些中间件给他打开 并且按照项目实际需求配置权重,越小越先执行)
SPIDER_MIDDLEWARES # 蜘蛛中间件 DOWNLOADER_MIDDLEWARES # 下载中间件 ITEM_PIPELINES # 管道
  • 1
  • 2
  • 3

二、代码演示

1. 主爬虫程序

  1. 初始化selenium (如果您不需要selenium,可以忽略这个
def __init__(self, *args,**kwargs): option = webdriver.ChromeOptions() # 实例化一个浏览器对象 option.add_argument('--headless') # 添加参数,option可以是headless,--headless,-headless self.driver = webdriver.Chrome(options=option) # 创建一个无头浏览器 # self.driver = webdriver.Chrome() # 创建一个无头浏览器 time.sleep(3) super(CnkiSpider, self).__init__(*args, **kwargs) dispatcher.connect(self.close_driver,signals.spider_closed)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 定义开始请求页面
    下面我只放了一个url,其实可以定义一组的然后进行遍历(一般是分页url使用)
    还有cookie、代理也可以在这里配置,详情请看进去看源码
    (不过一般在中间件配置)
def start_requests(self): for url in self.start_urls: yield scrapy.Request( # 这里可以设置多个页面,一般用于分页的 url=url, )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 关闭selenium(一定要关掉)
def close_driver(self): print("爬虫正在退出,执行关闭浏览器哦") time.sleep(2) self.driver.quit()
  • 1
  • 2
  • 3
  • 4
  1. 解析页面
    这里就不多说,八仙过海各显神通
def parse(self,response: HtmlResponse): sel = Selector(response) dds = sel.css('.journal > .main-w1 > dl > dd') for dd in dds: title = dd.css('h6 > a::attr(title)').extract_first() link = dd.css('h6 > a::attr(href)').extract_first() link = response.urljoin(link) author = dd.css('.baseinfo > span > #author::attr(title)').extract_first() abstract = dd.css('.abstract::text').extract_first() count = dd.css('.opts > .opts-count > li > em::text').extract_first() count = int(count) date = dd.css('.opts > .opts-count > .date::text').extract_first() date = date.split(':')[1] date = datetime.datetime.strptime(date,"%Y-%m-%d") rc = Recommend() rc['title'] = title rc['link'] = link rc['author'] = author rc['abstract'] = abstract rc['count'] = count rc['date'] = date yield rc
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这里要注意我们yield可以返回不仅是item,也可以是Request,进行页面详情的请求(套娃)

yield Request( url=link, # 这是上面页面上的链接,用来进一步请求 callback=self.parse_detail, # 这是回调函数 cb_kwargs={'item':rc} # 这是把上面的item传递下来 )
  • 1
  • 2
  • 3
  • 4
  • 5

2. 中间件的配置

  1. 针对selenium
    没有selenium请忽略
class SeleniumDownloaderMiddleware: def process_request(self, request , spider): if spider.name == 'cnki': spider.driver.get(request.url) time.sleep(2) print(f"当前访问{request.url}") spider.driver.refresh() time.sleep(3) return HtmlResponse(url=spider.driver.current_url,body=spider.driver.page_source,encoding='utf-8')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. SpiderMiddleware保持默认配置即可
  2. DownloaderMiddleware可以配置cookie和代理之类的。如:
# 我自定义的解析cookie方法 def get_cookie_dict(): cookie_str = 填上你的cookie cookie_dict = {} for item in cookie_str.split(';'): key, value = item.split('=',maxsplit=1) cookie_dict[key] = value return cookie_dict COOKIES_DICT = get_cookie_dict()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
# 这是DownloaderMiddleware这是自带的方法哈 def process_request(self, request : Request, spider): request.cookies = COOKIES_DICT return None
  • 1
  • 2
  • 3
  • 4

3. 定义item对象

用来接受爬虫到的数据

class Recommend(scrapy.Item): title = scrapy.Field() author = scrapy.Field() abstract = scrapy.Field() link = scrapy.Field() count = scrapy.Field() date = scrapy.Field()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4. 定义管道

实现对数据库的导入(你也可以写excel的)

class RecommendPipeline: @classmethod def from_crawler(cls, crawler: Crawler): host = crawler.settings['DB_HOST'] port = crawler.settings['DB_PORT'] username = crawler.settings['DB_USER'] password = crawler.settings['DB_PASSWORD'] database = crawler.settings['DB_DATABASE'] return cls(host, port, username, password, database) def __init__(self, host, port, username, password, database): # 1、与数据库建立连接 self.conn = pymysql.connect(host=host, port=port, user=username, password=password, database=database, charset='utf8mb4') # 2、创建游标 self.cursor = self.conn.cursor() # 3、批处理需要的容器 self.data = [] def process_item(self, item, spider): title = item.get('title', '') author = item.get('author', '') abstract = item.get('abstract', '') link = item.get('link', '') count = item.get('count', '') date = item.get('date', '') # 如果要实现批处理: self.data.append((title,author,abstract,link,count,date)) # 如果存够了10条就进数据库 if len(self.data) == 10: self._to_write_db() # 然后再清空 self.data.clear() return item def close_spider(self, spider): # 如果最后不满足10条 if len(self.data) > 0: self._to_write_db() self.conn.close() def _to_write_db(self): # 作为一个实时的推荐,我希望将查到的数据作为一个temp # 'delete from tb_recommend where 1 = 1' 删除满,并且主键自增不会从1开始 self.cursor.execute( 'truncate table tb_recommend' ) self.cursor.executemany( 'insert into tb_recommend (title,author,abstract,link,count,date) values (%s, %s, %s, %s, %s, %s)', self.data ) self.conn.commit()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

记得写入setting.py,设置其权重。
*接下来您就可以按照这种方法‘愉’ ‘快’的进行爬虫啦!!! *

总结

这是scrapy和selenium的具体整合使用,scrapy框架的内容还有很多方法还没用到,都有待开发。其次就是selenium的填充之类的操作还没有使用,还需要去复习selenium的api。

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索