码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Python爬虫采集框架——Scrapy初学入门


    一、安装Scrapy依赖包

    pip install Scrapy

    二、创建Scrapy项目(tutorial)

    scrapy startproject tutorial

    项目目录包含以下内容

    1. tutorial/
    2. scrapy.cfg # deploy configuration file
    3. tutorial/ # project's Python module, you'll import your code from here
    4. __init__.py
    5. items.py # project items definition file
    6. middlewares.py # project middlewares file
    7. pipelines.py # project pipelines file
    8. settings.py # project settings file
    9. spiders/ # a directory where you'll later put your spiders
    10. __init__.py

    三、tutorial/spiders目录下编写蜘蛛(quotes_spider.py)

    1、蜘蛛(version1.0)

    1. import scrapy
    2. class QuotesSpider(scrapy.Spider):
    3. name = "quotes"
    4. def start_requests(self):
    5. urls = [
    6. 'http://quotes.toscrape.com/page/1/',
    7. 'http://quotes.toscrape.com/page/2/',
    8. ]
    9. for url in urls:
    10. yield scrapy.Request(url=url, callback=self.parse)
    11. def parse(self, response):
    12. page = response.url.split("/")[-2]
    13. filename = f'quotes-{page}.html'
    14. with open(filename, 'wb') as f:
    15. f.write(response.body)
    16. self.log(f'Saved file {filename}')

    蜘蛛类QuotesSpider必须得继承scrapy.Spider,并定义以下属性和方法:

    name:蜘蛛名称(它在一个项目中必须是唯一的)

    start_requests():蜘蛛开始请求(方法返回的是请求的iterable)

    请求:scrapy.Request(url=url, callback=self.parse)

    parse():蜘蛛解析请求的响应(Response参数是响应的页面内容)

    2、蜘蛛(version2.0)

    1. import scrapy
    2. class QuotesSpider(scrapy.Spider):
    3. name = "quotes"
    4. start_urls = [
    5. 'http://quotes.toscrape.com/page/1/',
    6. 'http://quotes.toscrape.com/page/2/',
    7. ]
    8. def parse(self, response):
    9. page = response.url.split("/")[-2]
    10. filename = f'quotes-{page}.html'
    11. with open(filename, 'wb') as f:
    12. f.write(response.body)

    只需定义start_urls属性,不需重写start_requests() 方法,由默认的start_requests()方法根据start_urls属性开始请求也可。

    3、蜘蛛(version3.0)

    页面HTML代码:

    1. <div class="quote">
    2. <span class="text">“The world as we have created it is a process of our
    3. thinking. It cannot be changed without changing our thinking.”span>
    4. <span>
    5. by <small class="author">Albert Einsteinsmall>
    6. <a href="/author/Albert-Einstein">(about)a>
    7. span>
    8. <div class="tags">
    9. Tags:
    10. <a class="tag" href="/tag/change/page/1/">changea>
    11. <a class="tag" href="/tag/deep-thoughts/page/1/">deep-thoughtsa>
    12. <a class="tag" href="/tag/thinking/page/1/">thinkinga>
    13. <a class="tag" href="/tag/world/page/1/">worlda>
    14. div>
    15. div>

    蜘蛛代码:

    1. import scrapy
    2. class QuotesSpider(scrapy.Spider):
    3. name = "quotes"
    4. start_urls = [
    5. 'http://quotes.toscrape.com/page/1/',
    6. 'http://quotes.toscrape.com/page/2/',
    7. ]
    8. def parse(self, response):
    9. for quote in response.css('div.quote'):
    10. yield {
    11. 'text': quote.css('span.text::text').get(),
    12. 'author': quote.css('small.author::text').get(),
    13. 'tags': quote.css('div.tags a.tag::text').getall(),
    14. }

    该蜘蛛将提取页面中的text、author和tags,并使用终端打印。

    4、蜘蛛(version4.0)

    下一页HTML代码:

    1. <ul class="pager">
    2. <li class="next">
    3. <a href="/page/2/">Next <span aria-hidden="true">→span>a>
    4. li>
    5. ul>

    蜘蛛代码:

    1. import scrapy
    2. class QuotesSpider(scrapy.Spider):
    3. name = "quotes"
    4. start_urls = [
    5. 'http://quotes.toscrape.com/page/1/',
    6. ]
    7. def parse(self, response):
    8. for quote in response.css('div.quote'):
    9. yield {
    10. 'text': quote.css('span.text::text').get(),
    11. 'author': quote.css('small.author::text').get(),
    12. 'tags': quote.css('div.tags a.tag::text').getall(),
    13. }
    14. next_page = response.css('li.next a::attr(href)').get()
    15. if next_page is not None:
    16. next_page = response.urljoin(next_page)
    17. yield scrapy.Request(next_page, callback=self.parse)

    该蜘蛛将提取页面中的text、author和tags,使用终端打印,提取下一页的地址并开始请求,以此递归。

    1. #做如下测试操作
    2. urljoin("http://www.xoxxoo.com/a/b/c.html", "d.html")
    3. #结果为:'http://www.xoxxoo.com/a/b/d.html'
    4. urljoin("http://www.xoxxoo.com/a/b/c.html", "/d.html")
    5. #结果为:'http://www.xoxxoo.com/d.html'
    6. urljoin("http://www.xoxxoo.com/a/b/c.html", "../d.html")
    7. #结果为:'http://www.xoxxoo.com/a/d.html'

    5、蜘蛛(version5.0)

    1. import scrapy
    2. class QuotesSpider(scrapy.Spider):
    3. name = "quotes"
    4. start_urls = [
    5. 'http://quotes.toscrape.com/page/1/',
    6. ]
    7. def parse(self, response):
    8. for quote in response.css('div.quote'):
    9. yield {
    10. 'text': quote.css('span.text::text').get(),
    11. 'author': quote.css('span small::text').get(),
    12. 'tags': quote.css('div.tags a.tag::text').getall(),
    13. }
    14. next_page = response.css('li.next a::attr(href)').get()
    15. if next_page is not None:
    16. yield response.follow(next_page, callback=self.parse)

    蜘蛛(version4.0)和蜘蛛(version5.0)的区别:scrapy.Request支持绝对URL,而response.follow支持相对URL,并返回一个请求实例。

    6、蜘蛛(version6.0)

    1. import scrapy
    2. class AuthorSpider(scrapy.Spider):
    3. name = 'author'
    4. start_urls = ['http://quotes.toscrape.com/']
    5. def parse(self, response):
    6. author_page_links = response.css('.author + a')
    7. yield from response.follow_all(author_page_links, self.parse_author)
    8. pagination_links = response.css('li.next a')
    9. yield from response.follow_all(pagination_links, self.parse)
    10. def parse_author(self, response):
    11. def extract_with_css(query):
    12. return response.css(query).get(default='').strip()
    13. yield {
    14. 'name': extract_with_css('h3.author-title::text'),
    15. 'birthdate': extract_with_css('.author-born-date::text'),
    16. 'bio': extract_with_css('.author-description::text'),
    17. }

    使用选择器选择元素,会默认返回href属性,因此response.css('li.next a::attr(href)')与response.css('li.next a')是一样的。

    response.follow_all与response.follow的区别是:前者返回多个请求实例的iterable,而后者返回一个请求 实例。

    通过设置 DUPEFILTER_CLASS,scrapy可以过滤掉已经访问过的URL,避免了重复请求。

    四、使用蜘蛛参数

    1. import scrapy
    2. class QuotesSpider(scrapy.Spider):
    3. name = "quotes"
    4. def start_requests(self):
    5. url = 'http://quotes.toscrape.com/'
    6. tag = getattr(self, 'tag', None)
    7. if tag is not None:
    8. url = url + 'tag/' + tag
    9. yield scrapy.Request(url, self.parse)
    10. def parse(self, response):
    11. for quote in response.css('div.quote'):
    12. yield {
    13. 'text': quote.css('span.text::text').get(),
    14. 'author': quote.css('small.author::text').get(),
    15. }
    16. next_page = response.css('li.next a::attr(href)').get()
    17. if next_page is not None:
    18. yield response.follow(next_page, self.parse)

    运行命令行

    scrapy crawl quotes -O quotes-humor.json -a tag=humor

    通过-a传递的参数,被蜘蛛的 __init__ 方法赋值为蜘蛛的属性。在本例中,通过getattr()获取该参数并使用。

    五、CSS选择器与XPath

    scrapy shell是一个交互式shell,可以用来快速调试scrape代码,特别是测试数据提取代码(CSS选择器与XPath)。打开命令如下:

    scrapy shell "http://quotes.toscrape.com/page/1/"

    网页源码:

    1. <head>
    2. <meta charset="UTF-8">
    3. <title>Quotes to Scrapetitle>
    4. <link rel="stylesheet" href="/static/bootstrap.min.css">
    5. <link rel="stylesheet" href="/static/main.css">
    6. head>

    CSS选择器提取代码

    1. //获取符合的数据的列表
    2. >>>response.css('title::text').getall()
    3. //获取第一个符合的数据,没有数据返回None
    4. >>>response.css('title::text').get()
    5. //获取第一个符合的数据,没有数据会引发IndexError
    6. >>>response.css('title::text')[0].get()
    7. //css选择器选择出来后进行正则匹配
    8. >>>response.css('title::text').re(r'Quotes.*')

    XPath提取代码

    1. >>>response.xpath('//title')
    2. [<Selector xpath='//title' data='Quotes to Scrape'>]
    3. >>>response.xpath('//title/text()').get()
    4. 'Quotes to Scrape'

    更多爬虫知识以及实例源码,可关注微信公众号:angry_it_man

  • 相关阅读:
    实现常驻任务除了避免昙花线程,还需要避免重返线程池
    L3-006 迎风一刀斩
    企业员工内部培训系统开发
    YOLOv5算法改进(22)— 更换主干网络MobileNetv3 + 添加CA注意力机制
    老板加薪!看我做的WPF Loading!!!
    git多人运动产生冲突该怎么解决
    信安软考——第七章 访问控制技术原理与应用
    基于python的django框架博客论坛交流系统
    踩坑记 BSS段的初始化
    我看见了黑洞
  • 原文地址:https://blog.csdn.net/xuyuanfan77/article/details/127941615
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号