一个Scrapy项目实现同时爬取不同的网站,网站内不同的站点

Posted ㄏ、Forgetˊ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个Scrapy项目实现同时爬取不同的网站,网站内不同的站点相关的知识,希望对你有一定的参考价值。

Scrapy作为一个优秀的Python爬虫框架,深受博主喜爱,尽管博主从事大部分工作是前端开发,但也会对爬虫,数据库以及后台的工作感兴趣。
最近又有了新的任务,能够以相同的数据库表结构去存储爬取的数据;在以往,博主虽然说会爬虫,但也只是非常浅显的,一个Scrapy项目只能跑一个爬虫,而实际上是可以在一个Scrapy项目中写多个爬虫的。

前期准备工作

创建一个新的Scrapy项目,在工作间文件夹打开控制台,输入以下命令:

scrapy startproject xxx(xxx为项目名)


像上图,当你电脑已经成功安装scrapy之后,只需这一句命令就可以创建一个全新的scrapy项目了
目录结构如下:

这里博主修改了一下目录结构,因总共要爬取三个不同的网站,在spiders文件夹下添加了site01_spider.pysite02_spider.pysite03_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,故需要Chromewebdriver支持,同时还需要相关的配置

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官方文档

以上是关于一个Scrapy项目实现同时爬取不同的网站,网站内不同的站点的主要内容,如果未能解决你的问题,请参考以下文章

scrapy爬虫基本实现和爬虫思想

python 使用scrapy框架爬取一个图书网站的信息

Scrapy爬虫爬取B站视频标题及链接

中国农产品信息网站scrapy-redis分布式爬取数据

scrapy抓取所有网站域名

scrapy结合selenium爬取淘宝等动态网站