分布式爬取顶点小说全站内容

这是一个简单的分布式爬虫,网站其实并不复杂,文章主要为了写一下分布式的布局。

首先使用命令 scrapy genspider -t crawl “爬虫名”  网址,创建一个爬虫。然后添加代码 

from scrapy_redis.spiders import RedisCrawlSpider

引入RedisCrawlSpider,并让爬虫继承于此。删除start_urls,并在rules中添加所需要的url的正则表达的:

class NovelSpiderSpider(RedisCrawlSpider):
    name = 'novel_spider'

    redis_key = 'novel_spider:start_urls'

    list_page_lin=LinkExtractor(allow=(r'https://www.23us.so/list/.*?html'))
    novel_page=LinkExtractor(allow=(r'https://www.23us.so/xiaoshuo/\d+.html'))
    chapter_page=LinkExtractor(allow=(r'https://www.23us.so/files/article/html/\d+/\d+/index.html'))
    contents_page=LinkExtractor(allow=(r'https://www.23us.so/files/article/html/\d+/\d+/\d+.html'))
    # print(novel_page)


    rules = (
        Rule(list_page_lin,follow=True),
        Rule(novel_page,callback='parse_intro',follow=True),
        Rule(chapter_page,follow=True,),
        Rule(contents_page,callback='parse_item',follow=True)
    )

follow=True或者follow=False,表示是否对网页进行深度抓取,因为scrapy_redis中本身存在去重的机制,所以我选择的都是True。然后在callback的回调解析中解析你所需要的内容,我分了两个库存储,一个存放内容介绍,一个存放具体的章节和内容。

def parse_item(self, response):
    print("===============================")

    # print(response.url)
    item = XiaoshuoItem()
    item['rr']="21"
    # item['url']=response.url
    item['n_name'] = response.xpath('//*[@id="amain"]/dl/dt/a[3]/text()').extract_first()
    item['c_name'] = response.xpath('//*[@id="amain"]/dl/dd[1]/h1/text()').extract_first()
    print(response.xpath('//*[@id="amain"]/dl/dd[1]/h1/text()').extract_first())
    ret = ''
    contents = response.xpath('//dd[@id="contents"]/text()').extract()
    for i in contents:
        ret += i
    item['c_contents'] = ret

    yield item

存储的时候由于是分连个库存储的,需要区分内容,所以我加了一个隐藏的字段“rr”,在pipeline中判断本字段的内容或者格式来区分存储的库,其实使用if isinstance(item,XiaoshuoItem),这样判断也可以,但是数据多的时候可能会出现问题,所以我使用了隐藏字段,字段之作判断,并不保存。

数据的存储,我把书本简介存到了MongoDB中,把书的内容存到了mysql中,当然其实所有内容存到redis中会更加快点,但是我还是选择了mysql,没啥,就是习惯了。我在存mysql的时候,每个小说创建了一个表,表名称就是小说名

class DingdianxiaoshuoPipeline(object):
    def __init__(self):
        self.conn=pymysql.connect(
            host=MYSQL_HOST,
            port=MYSQL_PORT,
            user=MYSQL_USER,
            passwd=MYSQL_PASSWORD,
            db=MYSQL_DB,
        )
        self.cursor=self.conn.cursor()


    def process_item(self, item, spider):
        # table_name = item['n_name']
        if type(item['rr'])==str:
            creat_table='CREATE TABLE IF NOT EXISTS {} (novel_chapter varchar(256),chapter_contents varchar(10000))'.format(item['n_name'])
            self.cursor.execute(creat_table)
            data=[(item['c_name'],item['c_contents']),]
            sql="INSERT INTO {} (novel_chapter,chapter_contents) VALUES (%s,%s)".format(item['n_name'])
            self.cursor.executemany(sql,data)
            self.conn.commit()
            return item
        else:
            return item

整体的框架大约就是这样,我运行了一下午,并未见报错。但是为了保险起见,我还是加入了动态代理池和随机User-Agent表示对网站创作者的尊重,由于数量太大,并没有抓取完成。

Cola是一个分布式爬虫框架,用户只需编写几个特定的函数,而无需关注分布式运行的细节。任务会自动分配到多台机器上,整个过程对用户是透明的。pip install pyyaml安装下载或者用git clone源码,假设在目录/to/pth/cola,将该路径添加到Python path中。一种简单的方法是在site-packages中添加pth文件。site-packages因系统而异,如果是windows,假设python 装在C:\python27,那么就是C:\python27\Lib\site-packages;如果是linux,那么应该是/usr/local /lib/pythonX.X/dist-packages。在site-packages下新建一个cola.pth文件,里面写上路径:/to/path/cola。Cola目前自带了若干个爬虫,在项目根目录下的contrib中。下面就wiki为例,分别说明如何在单机和分布式环境下运行。依赖无论是维基百科还是新浪微博的实现,数据都存放在MongoDB中,所以要确保MongoDB的安装。在wiki下的wiki.yaml和weibo下的weibo.yaml中可以配置MongoDB的主机和端口。维基百科和新浪微博实现依赖于下面的几个包:mechanizepython-dateutilBeautifulSoup4mongoenginersa(仅新浪微博需要)可以使用pip或者easy_install来安装。单机模式单机模式非常简单,只需运行contrib/wiki/__init__.py即可。cd /to/path/cola/contrib/wiki python __init__.py要运行新浪微博的爬虫,需要在weibo.yaml中配置登录的用户名和密码。这里要注意,要保证这个用户名和密码在登录时不需要验证码。停止则需运行stop.py,注意不能通过直接杀死进程来停止,否则会导致cola非法关闭。 如果非法关闭,确保cola不在运行的情况下,则可以运行stop.py来恢复。但无论如何,都不推荐非法关闭,否则可能遇到不可预知的错误。python stop.py分布式模式首先需要启动cola master和cola workers。分别运行根目录下bin中的start_master.py和start_worker.py启动cola master:cd /to/path/cola python bin/start_master.py --data /my/path/data如果不指定--data,那么数据文件会放置在项目根目录下的data文件夹中。启动cola worker:python bin/start_worker.py --master <master ip address> --data /my/path/data--data选项同master。如果不指定master,会询问是否连接到本机master,输入yes连接。最后使用bin下的coca.py来运行指定的Cola job:python bin/coca.py -m <master ip address> -runLocalJob /to/path/cola/contrib/wiki-runLocalJob选项是要运行的job所在文件夹的绝对路径。输入命令后,该job会被提交到Cola集群来运行。停止Cola Job或集群停止整个集群,则可以运行:python bin/coca.py -m <master ip address> -stopAll而停止一个Job,则需要查询得到Job的名称:python bin/coca.py -m <master ip address> -showRunningJobsNames得到名称后,再运行:python bin/coca.py -m <master ip address> -stopRunningJobByName <job name>基于Cola实现的爬虫基于Cola实现的爬虫位于contrib/目录下。目前实现了四个爬虫:wiki:维基百科。weibo:新浪微博爬虫。从初始用户出发,然后是其关注和粉丝,依次类推,抓取指定个数的新浪微博用户的微博、个人信息、关注和粉丝。其中,用户微博只获取了内容、赞的个数、转发和评论的个数等等,而没有具体去获取此微博被转发和评论的内容。generic(unstable):通用爬虫,只需配置,而无需修改代码。目前Cola实现了一个抽取器(cola/core /extractor),能够从网页正文中自动抽取主要内容,即去除类似边栏和底脚等内容。但是,此抽取器目前准确度还不够,效率也不够高,所以需要谨慎 使用。weibosearch(unstable):新浪微博搜索的爬虫。这个爬虫使用 cola.core.opener.SpynnerOpener,基于spynner实现了一个Opener能够执行JavaScript和Ajax代 码。目前这个爬虫存在的问题是:新浪微博可能会将其识别成机器人,因此有可能会让输入验证码。wiki和weibo之前有所提及。主要说明generic和weibosearch。对于generic来说,主要要修改的就是配置文件:job:   patterns:     - regex: http://blog.sina.com.cn/$       name: home       store: no       extract: no     - regex: http://blog.sina.com.cn/s/blog_.       name: article       store: yes       extract: yes其中,regex表示要匹配的url的正则表达式;name是正则匹配的名称;store为yes时是存储这个网页,no为不存储;extract表示是否自动抽取网页正文,只有当store为yes的时候,extract才有作用。对于weibosearch,其使用了spynner来执行JavaScript和Ajax代码。所以需要确保以下依赖的安装:PyQt4(>=4.4.3)spynner如果你觉得可以基于cola实现一个比较通用的第三方爬虫,比如说腾讯微博等等,欢迎将此爬虫提交到contrib/中。编写自定义Cola Job见wiki编写自定义Cola Job。架构和原理在Cola集群里,当一个任务被提交的时候,Cola Master和Worker会分别启动JobMaster和JobWorker。对于一个Cola Job,当JobWorker启动完成后,会通知JobMaster,JobMaster等待所有JobWorker启动完成后开始运行Job。在一个 Cola Job启动时,会启动一个消息队列(Message Queue,主要操作是put和get,worker抓取到的对象会被put到队列中,而要抓取新的对象时,只要从队列中取即可),每个 JobWorker上都存在消息队列节点,同时会有一个去重模块(bloom filter实现)。Cola还不够稳定,目前会处于持续改进的状态。且Cola还没有在较大规模的集群上测试,但是接下来我会把Cola应用到新项目中,并逐步完善。也希望大家也能给我反馈,并帮助改进。Roadmap0.1版本正式推出前不会再增加新的功能了,主要目标让Cola更加稳定,并且提高cola/core/extractor的性能和精确度,完善contrib/generic和contrib/weibosearch。0.2版本计划:实现一个web接口,可以查看运行的cola job以及运行情况简化安装,支持easy_install或者pip安装。增加解决依赖库安装的机制。0.3版本计划:增加一个统一持久化抽象,支持保存到关系型数据库,MongoDB,文件系统,HDFS等等。0.4版本计划:支持Python 3 标签:Cola
<think>嗯,用户问的是分布式爬取是同时运行多个任务还是异步。我需要先理解这两个概念的区别和联系。分布式爬取通常指的是在多台机器上运行爬虫任务,而同时运行多个任务可能指的是并发,比如多线程或多进程。异步则是一种编程模型,通过非阻塞IO来提高效率。 首先,用户可能对分布式爬取的基本概念不太清楚,需要先解释什么是分布式爬取。然后,用户可能在纠结分布式到底是并行执行还是异步执行,或者两者都有。需要说明分布式主要涉及多节点协作,而并行和异步是单机上的优化手段。 接下来,要区分同时运行多个任务和异步的区别。同时运行多个任务属于并发,可能用多线程或多进程,而异步则是单线程内通过事件循环处理多个任务。分布式爬取可能同时使用这两种技术,比如每个节点内部用异步提高效率,节点之间分布式部署增加整体吞吐量。 还要考虑用户可能的实际需求。他们可能想优化爬虫效率,但不确定该选择分布式还是异步。需要指出两者的适用场景:分布式适合大规模数据,解决IP封锁等问题;异步适合高IO密集型任务,减少等待时间。 另外,用户可能没有明确区分并发和异步,需要简单说明两者的不同。例如,并发是同时处理多个任务,可能依赖多线程,而异步是单线程内非阻塞处理,更高效但编程复杂。 最后,总结两者的关系,说明分布式爬取可以结合并行和异步技术,既在多台机器上分布任务,又在单机上用异步提升性能,从而最大化效率。这样用户就能理解分布式爬取的综合优势,并根据自身情况选择合适的方案。</think>分布式爬取与**同时运行多个任务(并行)**、**异步**是不同维度的概念,但三者可以结合使用以提高爬取效率。以下是具体说明: --- ### 1. **分布式爬取** - **核心思想**:将爬虫任务拆分到**多台机器**上协同执行,通过分工合作提升整体效率。 - **特点**: - **横向扩展**:通过增加机器数量应对大规模数据抓取。 - **容错性**:单节点故障不影响整体任务。 - **解决封锁**:分布式 IP 池可降低被目标网站封禁的风险。 - **实现方式**: - 使用分布式框架(如 Scrapy-Redis、Celery)协调多台机器的任务分配与结果汇总。 --- ### 2. **同时运行多个任务(并行/并发)** - **核心思想**:在**单台机器**上通过多线程、多进程或协程同时处理多个爬取任务。 - **特点**: - **资源高效利用**:充分利用 CPU 和网络带宽。 - **实现简单**:例如 Python 的 `ThreadPoolExecutor` 或 `multiprocessing` 模块。 - **与分布式的区别**:并行仅在单机层面,无法突破硬件资源上限。 --- ### 3. **异步(Asynchronous)** - **核心思想**:通过**非阻塞 I/O** 和事件循环,单线程内高效处理多个网络请求。 - **特点**: - **低资源消耗**:适合高 I/O 密集型任务(如爬虫等待响应)。 - **编程复杂度**:需使用 `asyncio`、`aiohttp` 等异步库,代码逻辑更复杂。 - **与分布式的结合**:可在分布式单节点内部使用异步,进一步提升节点效率。 --- ### 三者关系示意图 ``` 分布式系统(多台机器) ├─ 节点1: 异步 + 多线程 ├─ 节点2: 异步 + 协程 └─ 节点3: 多进程 ``` --- ### 如何选择? - **小规模数据**:单机异步或多线程即可。 - **大规模/防封禁需求**:分布式 + 异步(单节点优化)+ IP 池。 - **CPU 密集型任务**:优先考虑多进程或分布式。 实际应用中,分布式爬虫往往会结合并行和异步技术,同时利用多台机器的资源与单机的高效 I/O 处理能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值