简书全站爬取 mysql异步保存
# 简书网
# 数据保存在mysql中; 将selenium+chromedriver集成到scrapy; 整个网站数据爬取
# 抓取ajax数据 #爬虫文件
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from jianshu_spider.items import ArticleItem class JsSpider(CrawlSpider):
name = 'js'
allowed_domains = ['jianshu.com']
start_urls = ['https://www.jianshu.com/'] # 从首页开始爬去 rules = (
# 详情页里面下面推荐的文章的href直接就是/p/.......
Rule(LinkExtractor(allow=r'.*/p/[0-9a-z]{12}.*'),
callback='parse_detail', follow=True),
) def parse_detail(self, response):
# print(response.text)
title = response.xpath("//div[@class='note']/div[@class='post']/div[@class='article']/h1[@class='title']/text()").get()
# print(title)
avatar = response.xpath("//a[@class='avatar']/img/@src").get()
# print(avatar)
author = response.xpath("//span[@class='name']/a/text()").get()
# print(author)
pub_time = response.xpath("//span[@class='publish-time']/text()").get().replace("*","")
# print(pub_time) # url正常情况下里面只有一个?
url = response.url
url1 = url.split("?")[0]
article_id = url1.split("/")[-1]
# print(article_id) # 把html标签一起趴下来, 方便以后展示
content = response.xpath("//div[@class='show-content']").get()
# print(content)
item = ArticleItem(
title=title,
avatar=avatar,
author=author,
pub_time=pub_time,
origin_url=response.url,
article_id=article_id,
content=content
)
yield item # item文件
import scrapy class ArticleItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field()
content = scrapy.Field()
article_id = scrapy.Field()
origin_url = scrapy.Field()
author = scrapy.Field()
avatar = scrapy.Field()
pub_time = scrapy.Field() # pipeline文件 保存在mysql中
import pymysql
from twisted.enterprise import adbapi # 专门做数据库处理的模块
from pymysql import cursors class JianshuSpiderPipeline(object):
def __init__(self):
dbparams={
'host':'127.0.0.1',
'port':3306,
'user':'root',
'password':'',
'database':'jianshu',
'charset':'utf8'
}
self.conn = pymysql.connect(**dbparams)
# **dbparams 相当于把 host='127.0.0.1' 写在了括号里 self.cursor = self.conn.cursor()
self._sql = None def process_item(self, item, spider):
self.cursor.execute(self.sql,(item['title'],item['content'],item['author'],item['avatar'],
item['pub_time'],item['origin_url'],item['article_id']))
self.conn.commit() # 这个是同步进行的 比较慢
return item @property
def sql(self):
if not self._sql: # 如果没有 执行
self._sql = '''
insert into article2(id,title,content,author,avatar,pub_time,
origin_url,article_id) values(null,%s,%s,%s,%s,%s,%s,%s)
'''
return self._sql
else:
return self._sql
# 优化上面的pipeline文件, 实现异步保存
# 使用twisted 提供的数据库连接池 ConnectionPool,把插入数据的动作变成异步的 (面试可以说) # 上面的存储是同步 比较慢, 现在优化成异步
class JianshuTwistedPipeline(object):
def __init__(self):
# 创建连接池
dbparams = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '',
'database': 'jianshu',
'charset': 'utf8',
'cursorclass':cursors.DictCursor
}
self.dbpool = adbapi.ConnectionPool('pymysql',**dbparams)
self._sql = None @property
def sql(self):
if not self._sql: # 如果没有 执行
self._sql = '''
insert into article2(id,title,content,author,avatar,pub_time,
origin_url,article_id) values(null,%s,%s,%s,%s,%s,%s,%s)
'''
return self._sql
else:
return self._sql def process_item(self,item,spider):
# runInteraction执行异步的
defer = self.dbpool.runInteraction(self.insert_item,item)
defer.addErrback(self.handle_error,item,spider) def insert_item(self,cursor,item): # 插入数据库
cursor.execute(self.sql,(item['title'],item['content'],item['author'],item['avatar'],
item['pub_time'],item['origin_url'],item['article_id'])) def handle_error(self,error,item,spider):
print('='*20)
print("error:",error)
print('='*20) # 把settings中的pipeline文件改一下
ITEM_PIPELINES = {
# 'jianshu_spider.pipelines.JianshuSpiderPipeline': 300,
'jianshu_spider.pipelines.JianshuTwistedPipeline': 300, # 异步保存数据
}
# 优化动态数据 处理ajax加载进来的数据
# selenium+chromdriver 处理 # 爬虫文件 把阅读量,点赞数,文章字数,标题分类,评论数 字段获取,保存到item中
def parse_detail(self, response):
# print(response.text)
title = response.xpath("//div[@class='note']/div[@class='post']/div[@class='article']/h1[@class='title']/text()").get()
print(title)
avatar = response.xpath("//a[@class='avatar']/img/@src").get()
# print(avatar)
author = response.xpath("//span[@class='name']/a/text()").get()
# print(author)
pub_time = response.xpath("//span[@class='publish-time']/text()").get().replace("*","")
# print(pub_time) # url正常情况下里面只有一个?
url = response.url
url1 = url.split("?")[0]
article_id = url1.split("/")[-1]
# print(article_id) # 把html标签一起趴下来, 方便以后展示
content = response.xpath("//div[@class='show-content']").get()
# print(content) # 动态获取下面的数据
word_count = response.xpath("//span[@class='wordage']/text()").get().split(" ")[-1]
read_count = response.xpath("//span[@class='views-count']/text()").get().split(" ")[-1]
comment_count = response.xpath("//span[@class='comments-count']/text()").get().split(" ")[-1]
like_count = response.xpath("//span[@class='likes-count']/text()").get().split(" ")[-1]
subject = response.xpath("//div[@class='include-collection']/a/div/text()").getall()
# subject 获取的时候一个列表 存到mysql的时候不支持, 需要把列表转成字符串
subject = ",".join(subject) item = ArticleItem(
title=title,
avatar=avatar,
author=author,
pub_time=pub_time,
origin_url=response.url,
article_id=article_id,
content=content, word_count=word_count,
read_count=read_count,
comment_count=comment_count,
like_count=like_count,
subject=subject,
)
yield item # 管道文件
# 上面的存储是同步 比较慢, 现在优化成异步
class JianshuTwistedPipeline(object):
def __init__(self):
# 创建连接池
dbparams = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '',
'database': 'jianshu',
'charset': 'utf8',
'cursorclass':cursors.DictCursor
}
self.dbpool = adbapi.ConnectionPool('pymysql',**dbparams)
self._sql = None @property
def sql(self):
if not self._sql: # 如果没有 执行
self._sql = '''
insert into article2(id,title,content,author,avatar,pub_time,
origin_url,article_id,read_count, word_count, like_count, comment_count,subject)
values(null,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
'''
# return self._sql
else:
return self._sql def process_item(self,item,spider):
# runInteraction执行异步的
defer = self.dbpool.runInteraction(self.insert_item,item)
defer.addErrback(self.handle_error,item,spider) def insert_item(self,cursor,item): # 插入数据库
cursor.execute(self.sql,(item['title'],item['content'],item['author'],item['avatar'],
item['pub_time'],item['origin_url'],item['article_id'],
item['read_count'],item['word_count'],item['like_count'],item['comment_count'],item['subject'])) def handle_error(self,error,item,spider):
print('='*20+'error'+'='*20)
print("error:",error)
print('='*20+'error'+'='*20)
简书全站爬取 mysql异步保存的更多相关文章
- Scrapy+selenium爬取简书全站
Scrapy+selenium爬取简书全站 环境 Ubuntu 18.04 Python 3.8 Scrapy 2.1 爬取内容 文字标题 作者 作者头像 发布日期 内容 文章连接 文章ID 思路 分 ...
- scrapy架构与目录介绍、scrapy解析数据、配置相关、全站爬取cnblogs数据、存储数据、爬虫中间件、加代理、加header、集成selenium
今日内容概要 scrapy架构和目录介绍 scrapy解析数据 setting中相关配置 全站爬取cnblgos文章 存储数据 爬虫中间件和下载中间件 加代理,加header,集成selenium 内 ...
- 基于selenium+phantomJS的动态网站全站爬取
由于需要在公司的内网进行神经网络建模试验(https://www.cnblogs.com/NosenLiu/articles/9463886.html),为了更方便的在内网环境下快速的查阅资料,构建深 ...
- scrapy_全站爬取
如何查询scrapy有哪些模版? scrapy genspider –list 如何创建crawl模版? scrapy genspider -t crawl 域名 scrapy genspider - ...
- Java两种方式简单实现:爬取网页并且保存
注:如果代码中有冗余,错误或者不规范,欢迎指正. Java简单实现:爬取网页并且保存 对于网络,我一直处于好奇的态度.以前一直想着写个爬虫,但是一拖再拖,懒得实现,感觉这是一个很麻烦的事情,出现个小错 ...
- python爬取网站数据保存使用的方法
这篇文章主要介绍了使用Python从网上爬取特定属性数据保存的方法,其中解决了编码问题和如何使用正则匹配数据的方法,详情看下文 编码问题因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这 ...
- Java爬虫一键爬取结果并保存为Excel
Java爬虫一键爬取结果并保存为Excel 将爬取结果保存为一个Excel表格 官方没有给出导出Excel 的教程 这里我就发一个导出为Excel的教程 导包 因为个人爱好 我喜欢用Gradle所以这 ...
- 爬虫---scrapy全站爬取
全站爬取1 基于管道的持久化存储 数据解析(爬虫类) 将解析的数据封装到item类型的对象中(爬虫类) 将item提交给管道, yield item(爬虫类) 在管道类的process_item中接手 ...
- crawlSpider全站爬取 分布式
# 如何提升scrapy爬取数据的效率? 推荐: 单线程加异步协程 增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增加.在settings.py中修改 CONCURRENT_REQU ...
随机推荐
- VisualStateManager
管理控件状态和管理控件状态的转换逻辑 <Window.Resources> <Style TargetType="Button" x:Key="Anim ...
- 2017 JavaScript 开发者的学习图谱
码云项目推荐 前端框架类 1.项目名称: 基于 Vue.js 的 UI 组件库 iView 项目简介:iView 是一套基于 Vue.js 的 UI 组件库,主要服务于 PC 界面的中后台产品. 特性 ...
- IDEA 自动化配置
# IDEA maven web项目:http://www.cnblogs.com/Sinte-Beuve/p/5730553.html # IDEA 数据库自动化 ## 功能 ① SQL 代码自动感 ...
- XAML的命名空间 - CSDN博客
原文:XAML的命名空间 - CSDN博客 一个最简单的XAML例子 <Window x:Class="WpfApplication1.MainWindow" xmlns=& ...
- PHP 实现自动加载器(Autoloader)
我们知道PHP可以实现自动加载,避免了繁重的体力活,代码更规范,整洁.那如果我们把这个自动加载再升华一下,变成自动加载类,每次只需要引入这个类,那么其他类就自动加载了,已经开源,仓库地址在这里.同时如 ...
- SQL Server 2017 SELECT…INTO 创建的新表指定到文件组
原文:SQL Server 2017 SELECT-INTO 创建的新表指定到文件组 SELECT-INTO 在 SQL Server 中也是常见的一个功能,过去用此方法创建的新表只能存储到默认的文件 ...
- EasyUI之combogrid
html代码: <div class="item-label">@Html.L("Name"):</div> <input id= ...
- javascript学习路线图
史上最全的javascript学习路线图 JavaSctipt学习路线 完成整个课程大纲需要花上6~8周的时间,将学会完整的JavaScript语言(包括jQuery和一些HTML5).如果你没有时间 ...
- delphi如何输出当前堆栈
想实现,输出当前运行的堆栈,有会的吗?给点思路 方法很多,参考: https://bitbucket.org/shadow_cs/delphi-leakcheck/ 的 https://bitbuck ...
- QThread多线程编程经典案例分析(三种方法,解释了为什么使用moveToThread的根本原因,即为了避免调用QThread::exec() )
传统的图形界面应用程序都只有一个线程执行,并且一次执行一个操作.如果用户调用一个比较耗时的操作,就会冻结界面响应. 一个解决方法是按照事件处理的思路: 调用 Void QApplication::pr ...