• 从零到一python爬虫实战:框架选择>查找爬虫参数>写代码>打包运行


    文章链接

    编号分类文章及链接介绍作者来源分类撰写日期收录日期
    F1框架Python有哪些常见的、好用的爬虫框架?知乎2020-12-082022-08-07
    I1安装从原理到实战,一份详实的 Scrapy 爬虫教程简洁明了Scraph从安装到开发出第一个实用爬虫例子。好文。开发者社区腾讯云2021-08-052022-08-08
    B1基础Running multiple spiders in the same process介绍Scraph如何并行或者按顺序启动多个爬虫官网文档scrapy官网2020-12-032022-08-08
    T1技巧scrapy头部修改详解介绍Scraph的四种请求header修改方式周少钦CSDN博客2020-12-032022-08-08
    T2工具爬虫必备工具,掌握它就解决了一半的问题介绍了chrome开发者工具的用法,很实用Crossin知乎2018-07-092022-08-08

    前言

    最近用了三天的零碎时间写了一个GEM的NFT稀有度排名的爬虫。从框架选择到打包好进入正式服务器运行,踩坑填坑费了一些周折,特此记录。

    1. 框架选择

    相信初次接触爬虫的人都存在一个选什么框架最合适的问题,我也不例外。参考了知乎的这篇文章,Python有哪些常见的、好用的爬虫框架?。 诸多回答中不约而同提到了scraph, 而且也提到scraph上手简单。有知乎回答者提到使用“requests + beautifulsoup4 + lxml 完美组合” 或者“gevent, requests, 正则, pyv8,动态静态全吃” 对于致力于爬虫开发者来讲,肯定是更好的选择。对于我这个偶尔使用者来讲,为了快速实现功能,还是定Scraph框架吧。

    2. Scrapy安装

    从原理到实战,一份详实的 Scrapy 爬虫教程简洁明了Scraph从安装到开发出第一个实用爬虫例子,参考此文即可安装好。

    3. Chrome/Postman查找验证爬虫参数

    正确的参数是能爬到数据的关键一环。爬虫必备工具,掌握它就解决了一半的问题介绍了chrome开发者工具查找参数的办法。很实用。
    Postman可以模拟发布请求,检查参数是是否正确或者必要,是找参数的好助手。

    4. 编写逻辑代码

    Scraph安装好,通过集成IDE里面的Scraph向导可以生成框架需要的源代码文件。
    在这里插入图片描述
    上图是标准文件夹结构及标准的撰写爬虫逻辑的代码文件。
    在spider下面的xxx.py里提交网络请求(start_requests())以及解析网络返回结果(parse(self, response))。
    在items.py 里面定义解析结果的数据项。
    在pipelines.py里面对根据解析生成的数据做最后的加工处理(process_item()),通常是将结果写入数据库,打印日志什么的。
    在settings.py里面配置爬虫参数。

    5. 打包发布及运行

    最常用的打包工具是pyinstaller. 按照pyinstaller 默认的方式打包到一个目录下。打包到文件的话(使用-F参数)会出现找不到设置的情况。

    pyinstaller start.py  
    
    • 1

    但是下面这种启动方式,打包运行会出错。

        # 脚本执行模式(不适合打包启动) gem是我的爬虫名字
        cmdline.execute('scrapy crawl gem'.split())
    
    • 1
    • 2

    5.1 启动方式使用CrawlerProcess替代cmdline.execute(‘scrapy crawl XXX’.split())

    需要对启动文件做一个修改。适合打包运行的写法:

    from scrapy.crawler import CrawlerProcess
    from scrapy.utils.project import get_project_settings
    from nftRankSpider.spiders.gem import GemSpider
    from nftRankSpider.pipelines import NftrankspiderPipeline
    from nftRankSpider.items import GemNftRankItem
    import nftRankSpider.settings
    
    def run_mycrawler():
        process = CrawlerProcess(get_project_settings())
        # crawl方法的启动参数为spider名称
        process.crawl(GemSpider)
        process.start()
    
    if __name__ == '__main__':
    	run_mycrawler()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Tips

    注意,imoprt的最后三项(NftrankspiderPipeline, GemNftRankItem, nftRankSpider.settings)虽然没有直接用到,但不做import的话,运行时会出现找不到某些模块的错误。import的最后四项对应的内容,都是框架生成可以自己修改代码的类或者代码块。

    5.2 Spider中添加warn_on_generator_with_return_value_stub方法并执行

    较高版本的scrapy在pyinstaller打包后,如果源代码中有yield方法,会有运行报错:scrapy OSError: could not get source code
    在spider(gem.py) 最后加入下面的四行语句可以解决这个打包问题(注意加入两行import语句) 参考Scrapy Pyinstaller OSError: could not get source code / twisted.internet.defer._DefGen_Return

    import scrapy.utils.misc
    import scrapy.core.scraper
    
    	class GemSpider(scrapy.Spider):
    		name = 'gem'
    	    allowed_domains = ['beta.gem.xyz', 'api-1.gemlabs.xyz', 'api-2.gemlabs.xyz', 'api-5.gemlabs.xyz']  # 可以修改
    	
    	    def start_requests(self):
    	    	...
    	    def parse(self, response):
    	    	...
    	
    	    def warn_on_generator_with_return_value_stub(spider, callable):
    	        pass
        	scrapy.utils.misc.warn_on_generator_with_return_value = warn_on_generator_with_return_value_stub
    	    scrapy.core.scraper.warn_on_generator_with_return_value = warn_on_generator_with_return_value_stub
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6 在同一个进程里面并行/串行启动多个爬虫

    参考scrapy官网的这篇文章Running multiple spiders in the same process

    6.1 并行启动多个爬虫

    参考下面的代码,使用CrawlerProcess

    import scrapy
    from scrapy.crawler import CrawlerProcess
    from scrapy.utils.project import get_project_settings
    
    class MySpider1(scrapy.Spider):
        # Your first spider definition
        ...
    
    class MySpider2(scrapy.Spider):
        # Your second spider definition
        ...
    
    settings = get_project_settings()
    process = CrawlerProcess(settings)
    process.crawl(MySpider1)
    process.crawl(MySpider2)
    process.start() # the script will block here until all crawling jobs are finished
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    或者使用CrawlerRunner

    import scrapy
    from twisted.internet import reactor
    from scrapy.crawler import CrawlerRunner
    from scrapy.utils.log import configure_logging
    from scrapy.utils.project import get_project_settings
    
    class MySpider1(scrapy.Spider):
        # Your first spider definition
        ...
    
    class MySpider2(scrapy.Spider):
        # Your second spider definition
        ...
    
    configure_logging()
    settings = get_project_settings()
    runner = CrawlerRunner(settings)
    runner.crawl(MySpider1)
    runner.crawl(MySpider2)
    d = runner.join()
    d.addBoth(lambda _: reactor.stop())
    
    reactor.run() # the script will block here until all crawling jobs are finished
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    6.2 按顺序执行多个爬虫(尚待验证)

    from twisted.internet import reactor, defer
    from scrapy.crawler import CrawlerRunner
    from scrapy.utils.log import configure_logging
    from scrapy.utils.project import get_project_settings
    
    class MySpider1(scrapy.Spider):
        # Your first spider definition
        ...
    
    class MySpider2(scrapy.Spider):
        # Your second spider definition
        ...
    
    configure_logging()
    settings = get_project_settings()
    runner = CrawlerRunner(settings)
    
    @defer.inlineCallbacks
    def crawl():
        yield runner.crawl(MySpider1)
        yield runner.crawl(MySpider2)
        reactor.stop()
    
    crawl()
    reactor.run() # the script will block here until the last crawl call is finished
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    shell实例第24讲:zookeeper启动、停止、查看状态脚本
    Celery框架从入门到精通
    获奖名单出炉 ,鲲鹏应用创新大赛2023全国总决赛圆满落幕
    golang学习之路2-基础认识(上)
    【云原生 | Kubernetes 系列】---Prometheus监控Nginx
    Cloudflare分析第一天:简单的算法反混淆
    基于PHP+MySQL汽车查询系统的设计与实现
    微软表示Visual Studio的IDE即日起开启“退休”倒计时
    Vue的`provide`和`inject`特性:上下文传递与数据共享
    AI杀疯!2023上半年至今有趣的AI算法(内附视频)
  • 原文地址:https://blog.csdn.net/sitebus/article/details/126208943