Scrapy 浅入浅出
前言
提到爬虫框架,除了各个公司自己开发的爬虫系统外,公共框架部分自然就会提到 Scrapy,它是一款非常强大的分布式异步爬虫框架。
本文就讲讲 Scrapy 的简单使用。
实战
安装依赖
# 安装依赖
pip3 install Scrapy# Mysql
pip3 install mysqlclient
创建项目及爬虫
分析目前地址,获取网站 HOST 及爬取地址,在某个文件夹下利用命令创建一个爬虫项目及一个爬虫
# 创建一个爬虫项目
scrapy startproject cqmmgo# 打开文件夹
cd cqmmgo# 创建一个爬虫
scrapy genspider talk 网站HOST
定义 Item 实体对象
在 items.py 文件中,将需要爬取的数据定义为 Item
比如,这里就需要爬取帖子标题、作者、阅读数、评论数、贴子 URL、发布时间
# items.pyimport scrapy# 杂谈
class CqTalkItem(scrapy.Item):# 标题title = scrapy.Field()# 作者author = scrapy.Field()# 查看次数watch_num = scrapy.Field()# 评论次数comment_num = scrapy.Field()# 地址address_url = scrapy.Field()# 发布时间create_time = scrapy.Field()
编写爬虫
在 spiders 文件夹下的爬虫文件中编写具体的爬虫逻辑
通过分析发现,帖子数据是通过模板直接渲染,非动态加载,因此我们直接对 response 进行数据解析
PS:解析方式这里推荐使用 Xpath
解析完成的数据组成上面定义的 Item 实体添加到生成器中
# spiders/talk.pyimport scrapy
from cqmmgo.items import CqTalkItem
from cqmmgo.settings import talk_hour_before
from cqmmgo.utils import calc_interval_hourclass TalkSpider(scrapy.Spider):name = 'talk'allowed_domains = ['HOST']# 第1-5页数据start_urls = ['https://HOST/forum-233-{}.html'.format(i + 1) for i in range(5)]def parse(self, response):# 直接Xpath解析elements = response.xpath('//div[contains(@class,"list-data-item")]')for element in elements:item = CqTalkItem()title = element.xpath('.//*[@class="subject"]/a/@title').extract_first()author = element.xpath(".//span[@itemprop='帖子作者']/text()").extract_first()watch_num = element.xpath(".//span[@class='num-read']/text()").extract_first()comment_num = element.xpath(".//span[@itemprop='回复数']/text()").extract_first()address_url = "https:" + element.xpath('.//*[@class="subject"]/a/@href').extract_first()create_time = element.xpath('.//span[@class="author-time"]/text()').extract_first().strip()# 过滤超过设定小时之前的数据if calc_interval_hour(create_time) > talk_hour_before:continueprint(f"标题:{title},作者:{author},观看:{watch_num},评论:{comment_num},地址:{address_url},发布时间:{create_time}")item['title'] = titleitem['author'] = authoritem['watch_num'] = watch_numitem['comment_num'] = comment_numitem['address_url'] = address_urlitem['create_time'] = create_timeyield item
自定义随机 UA 下载中间件
在 middlewares.py 文件中自定义随机 User Agent 下载中间件
# middlewares.pyimport random # 导入随机模块class RandomUADownloaderMiddleware(object):def process_request(self, request, spider):# UA列表USER_AGENT_LIST = ['Opera/9.20 (Macintosh; Intel Mac OS X; U; en)','Opera/9.0 (Macintosh; PPC Mac OS X; U; en)','iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)','Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)','iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)','Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0','Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)','Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)']# 随机生成一个UAagent = random.choice(USER_AGENT_LIST)# 设置到请求头中request.headers['User_Agent'] = agent
自定义下载管道 Pipline
在 piplines.py 文件中,自定义两个下载管道,分别将数据写入到本地 CSV 文件和 Mysql 数据中
PS:为了演示方便,这里仅展示同步写入 Mysql 数据库的方式
# piplines.pyfrom scrapy.exporters import CsvItemExporter
from cqmmgo.items import CqTalkItem
import MySQLdb # 导入数据库模块class TalkPipeline(object):"""杂谈"""def __init__(self):self.file = open("./result/talk.csv", 'wb')self.exporter = CsvItemExporter(self.file, fields_to_export=['title', 'author', 'watch_num', 'comment_num', 'create_time', 'address_url'])self.exporter.start_exporting()def process_item(self, item, spider):if isinstance(item, CqTalkItem):self.exporter.export_item(item)return item# 关闭资源def close_spider(self, spider):self.exporter.finish_exporting()self.file.close()# 数据存入到数据库(同步)
class MysqlPipeline(object):def __init__(self):# 链接mysql数据库self.conn = MySQLdb.connect("host", "root", "pwd", "cq", charset="utf8", use_unicode=True)self.cursor = self.conn.cursor()def process_item(self, item, spider):table_name = 'talk'# sql语句insert_sql = """insert into {}(title,author,watch_num,comment_num,address_url,create_time,insert_time) values(%s,%s,%s,%s,%s,%s,%s) """.format(table_name)# 从item获得数据,保存为元祖,插入数据库params = list()params.append(item.get("title", ""))params.append(item.get("author", ""))params.append(item.get("watch_num", 0))params.append(item.get("comment_num", 0))params.append(item.get("address_url", ""))params.append(item.get("create_time", ""))params.append(current_date())# 执行插入数据到数据库操作self.cursor.execute(insert_sql, tuple(params))# 提交,保存到数据库self.conn.commit()return itemdef close_spider(self, spider):"""释放数据库资源"""self.cursor.close()self.conn.close()
当然,这里也可以定义一个数据去重的数据管道,通过帖子标题,对重复的数据不进行处理即可
# piplines.pyfrom scrapy.exceptions import DropItemclass DuplicatesPipeline(object):"""Pipline去重"""def __init__(self):self.talk_set = set()def process_item(self, item, spider):name = item['title']if name in self.talk_set:raise DropItem("重复数据,抛弃:%s" % item)self.talk_set.add(name)return item
配置爬虫配置文件
打开 settings.py 文件,对下载延迟时间、默认请求头、下载中间件、数据管道进行编辑
# settings.py# Obey robots.txt rules
ROBOTSTXT_OBEY = FalseDOWNLOAD_DELAY = 3# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','Accept-Language': 'zh-CN,zh;q=0.9','Host': 'HOST','Referer': 'https://HOST/forum-233-1.html','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',
}DOWNLOADER_MIDDLEWARES = {'cqmmgo.middlewares.RandomUADownloaderMiddleware': 543,'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
}ITEM_PIPELINES = {'cqmmgo.pipelines.TalkPipeline': 1,'cqmmgo.pipelines.MysqlPipeline': 6,'cqmmgo.pipelines.DuplicatesPipeline': 200,'cqmmgo.pipelines.CqmmgoPipeline': 300,
}# 爬取时间限制
talk_hour_before = 24
爬虫主入口
在爬虫项目根目录下创建一个文件,通过下面的方式运行单个爬虫
# main.pyfrom scrapy.cmdline import execute
import sys, osdef start():sys.path.append(os.path.dirname(__file__))# 运行单个爬虫execute(["scrapy", "crawl", "talk"])if __name__ == '__main__':start()
最后
如果 Scrapy 项目中包含多个爬虫,我们可以利用 CrawlerProcess 类并发执行多个爬虫
# main.pyfrom scrapy.utils.project import get_project_settings
from scrapy.crawler import CrawlerProcess# 同时运行项目下的多个爬虫
def start():setting = get_project_settings()process = CrawlerProcess(setting)# 不运行的爬虫spider_besides = ['other']# 所有爬虫for spider_name in process.spiders.list():if spider_name in spider_besides:continueprint("现在执行爬虫:%s" % (spider_name))process.crawl(spider_name)process.start()if __name__ == '__main__':start()
Scrapy 浅入浅出相关推荐
- [科普]浅入浅出Liunx Shellcode
创建时间:2008-05-13 文章属性:原创 文章提交: pr0cess (pr0cess_at_cnbct.org) 浅入浅出Liunx Shellcode /*---------------- ...
- 浅入深出之Java集合框架(上)
Java中的集合框架(上) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到浅入深出之Java集合框架(下). ...
- 浅入深出之Java集合框架(中)
Java中的集合框架(中) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到浅入深出之Java集合框架(下). ...
- Angular浅入深出系列 - 写在前面
本系列目录: 写在前面 基础知识 控制器(Controller) 作用域(Scope) 集合(Collection) 模块(Module) 依赖注入(Dependency Injection) 服务( ...
- SegmentFault 技术周刊 Vol.16 - 浅入浅出 JavaScript 函数式编程
函数式编程(Functional Programming),一看这个词,简直就是学院派的典范. 以至于从 Lisp 的创世,到 Scheme.Haskell.Clean.Erlang.Miranda. ...
- 浅入浅出深度学习理论实践
全文共9284个字,40张图,预计阅读时间30分钟. 前言 之前在知乎上看到这么一个问题:在实际业务里,在工作中有什么用得到深度学习的例子么?用到 GPU 了么?,回头看了一下自己写了这么多东西一直围 ...
- 浅入浅出 Android 安全 翻译完成!
浅入浅出 Android 安全 翻译完成! 作者:Yury Zhauniarovich 译者:飞龙 来源:Yury Zhauniarovich | Publications 在线阅读 PDF格式 EP ...
- 浅入深出Vue:环境搭建
浅入深出Vue:环境搭建 工欲善其事必先利其器,该搭建我们的环境了. 安装NPM 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版本的NodeJS Windows安装程序 下载下来后,直 ...
- 处理中文乱码_浅入深出:一次提问引发的深思,从此再也不怕“乱码”问题
这是恋习Python之浅入深出系列第3篇原创首发文章 作者|丁彦军 来源|恋习Python(ID:sldata2017) 转载请联系授权(微信ID:2394608316) 近日,有位粉丝向我请教,在爬 ...
- Java 注解 (Annotation)浅入深出
Java 注解 (Annotation)浅入深出 本文主要参考与借鉴frank909 文章,但更为简单,详细. Annotation 中文译过来就是注解.标释的意思.Annotation是一种应用于类 ...
最新文章
- MarkDown入门及技巧
- 北京师范大学计算机系录取分数线,北京师范大学各省各专业录取分数线
- Linux的phpize
- 实验3 分支语句和循环语句(1)
- React-Router面试题汇总
- Spring中@Async
- yshon对讲机如何调频率_窄带宽、窄脉宽、高重复频率,主动调Q光纤激光器是如何实现的?...
- 迪普交换机恢复出厂设置_LSW交换机初始化配置指导
- 去掉WPS智能生成目录中的空白行
- 微软云服务Azure所有产品简介
- 移动网购掀起新一轮掘金潮 电商群启战略布局(转)
- 12种 vo2dto 方法,就 BeanUtils.copyProperties 压测最拉胯!【快双11了,别用错喽】
- 再见postman,被这个一站式接口管理工具折服了
- 来着QQ邮箱的垃圾网页分析,能力有限,没什么实际的进展
- Efficient Parameter-free Clustering Using First Neighbor Relations
- JVM: java虚拟机
- 创作者运营—创作者课程开发思路
- 如何运用python画名字_[原创]如何使用Python在好友画我上画一个标准的汉字震惊朋友圈...
- 关于顶尖PS1XD的使用方法
- 远程访问大华摄像头拍摄的视频
热门文章
- (翻译)网站品质与配色相关
- 四舍、六入、五凑偶之Math.Round()
- Windows 11 下 Virtualbox 6.1.34 出现 End kernel panic - not syncing: attempted to kill the idle task
- winserver 443端口被system占用_手机系统占用内存越来越大,是谁的锅?
- 288.软件开发过程与软件测试
- 保护信息安全,实名认证该怎么选?
- 如何修改win7上的mac地址
- 2.8 CSS3新特性
- 全量表/增量表/快照表
- mysql数据库基操所遇问题及相关知识及命令记录