Scrapy作为一个优秀的Python爬虫框架,深受博主喜爱,尽管博主从事大部分工作是前端开发,但也会对爬虫,数据库以及后台的工作感兴趣。
最近又有了新的任务,能够以相同的数据库表结构去存储爬取的数据;在以往,博主虽然说会爬虫,但也只是非常浅显的,一个Scrapy项目只能跑一个爬虫,而实际上是可以在一个Scrapy项目中写多个爬虫的。
前期准备工作
创建一个新的Scrapy项目,在工作间文件夹打开控制台,输入以下命令:
scrapy startproject xxx(xxx为项目名)
像上图,当你电脑已经成功安装scrapy之后,只需这一句命令就可以创建一个全新的scrapy项目了
目录结构如下:
这里博主修改了一下目录结构,因总共要爬取三个不同的网站,在spiders文件夹下添加了site01_spider.py,site02_spider.py,site03_spider.py三个爬虫文件,在demo目录下添加db.py数据库存储文件,在最外层大目录下添加demo_main.py启动爬虫文件,如下图:
编写代码工作
db.py(新增):配置相关的SQL初始化创建表方法,数据库插件mysql使用pymysql插件,mssql则使用pymssql插件。
import pymssql
class demoInfo(object): def __init__(self, tableName): self.tableName = tableName
def add(self, xxx): # 这里做连接数据库,插入数据库操作 db = pymssql.connect( host="xxx", user="xxx", password="xxx", database="xxx" ) cursor = db.cursor() sql = "select * from 'xxxx'" cursor.execute(sql) db.commit() cursor.close() db.close()
def create(self, xxx): # 这里做初始化创建表操作 SQL语句有变 基本同上 print('create')
items.py:配置需要爬取的字段。
class DemoItem(scrapy.Item): # define the fields for your item here like: name = scrapy.Field() pass
middlewares.py:可编写用于随机选取USER_AGENTS的类方法,按需也可在下载中间件process_response回调里使用selenium做请求回调前的控制浏览器行为的操作(这里不做展开)。
pipelines.py:可根据爬虫名称来区分要插入的数据库。
from source.db import dbInfo
class DemoPipeline(object): def process_item(self, item, spider): dbName = '' # 根据蜘蛛名来判断数据库的表名 if spider.name == 'site01_spider': dbName = 'site01' elif spider.name == 'site02_spider': dbName = 'site02' else: dbName = 'site03' source = dbInfo(dbName) source.create(dbName) source.add(item["name"]) return item
settings.py:项目配置文件,按需配置(这里也不做展开)。
source_main.py(新增):该文件作为爬虫启动的入口文件,可由用户输入决定所要启动的爬虫。
from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings from demo.spiders.site01_spider import site01Spider from demo.spiders.site02_spider import site02Spider from demo.spiders.site03_spider import site03Spider from demo.db import dbInfo
# 在Scrapy框架内控制爬虫 if __name__ == "__main__": process = CrawlerProcess(get_project_settings())
# 控制台主界面 main = int(input("请输入爬取网站:(1为site01 2为site02 3为site03)")) if main == 1: process.crawl("site01_spider") elif main == 2: process.crawl("site02_spider") elif main == 3: process.crawl("site03_spider") else: print("输入错误!") pass
print('—–爬虫启动—–') process.start()
site01到site03爬虫文件,这里举其中一个文件为例展开:
博主使用到了selenium,故需要Chrome的webdriver支持,同时还需要相关的配置
import scrapy from demo.items import DemoItem from selenium import webdriver from selenium.webdriver.chrome.options import Options # 使用无头浏览器
# 无头浏览器设置 chorme_options = Options() chorme_options.add_argument("–headless") chorme_options.add_argument("–disable-gpu")
class site01Spider(scrapy.Spider): name = 'site01_spider' allowed_domains = [ 'www.site01xx.com', 'www.site01yy.com', 'www.site01zz.com' ] start_urls = [ 'https://www.site01xx.com/list/index.html' ]
def __init__(self): self.page = 1 # 当前页码 self.url_index = 0 # 当前url_list的下标值 # url_list可配置相同的网页结构,不同的站点的url,可支持不同的域名 # 如果为不同域名,需要在allowed_domains添加对应的允许域名 self.url_list = [ 'https://www.site01xx.com/list/index.html', 'https://www.site01yy.com/list/index.html', 'https://www.site01zz.com/list/index.html' ] self.browser = webdriver.Chrome(chrome_options=chorme_options) super().__init__()
# 整个爬虫结束后关闭浏览器 def close(self, spider): print('退出爬虫') self.browser.quit()
def parse(self, response): # 每进入一次回调,page就自加1(页码) self.page = self.page + 1
# 回调中对数据进行清洗,以及判断是否需要进行切页,进入详情页的操作 item = DemoItem() name = 'xxx' # 操作的最后,将数据压入字段后,传输给管道 item['name'] = name yield item
# 假设总页码为100,爬完100页后进入下一个站点 if self.page <= 100: yield scrapy.Request(url=self.url_list[self.url_index] + "?page=" + str(self.page), callback=self.parse) else: # 进入这里,证明已经爬完了某一个站点 print('—–进入下一个站点—–') self.page = 1 # 页码重置为1 self.url_index = self.url_index + 1 # 数组下标自增1 yield scrapy.Request(url=self.url_list[self.url_index], callback=self.parse)
到这基本上就完成demo的编写,仅需按照自身需求替换相对应的示例代码即可完成。
总结
尽管爬虫并非博主的编程方向,但是博主还是非常乐意去钻研学习,多学习一些别的技术,对自身的提升还是非常有帮助的!
博主作为Python菜鸟级选手,文章有哪里写得不对的地方还请慷慨指出;同样的,有什么不懂的小伙伴也可以留言,博主当会尽力解答,大家一起共同进步!
参考网站:Scrapy官方文档
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试