第8章 scrapy项目练习

第8章 项目练习

  在一本书的页面中可以获取以下信息:
  ● 书名√
  ● 价格√
  ● 评价等级√
  ● 书籍简介
  ● 产品编码√
  ● 产品类型
  ● 税价
  ● 库存量√
  ● 评价数量√

8.1 项目需求

  爬取http://books.toscrape.com网站中的书籍信息。

(1)其中每一本书的信息包括:

  1. 书名
  2. 价格
  3. 评价等级
  4. 产品编码
  5. 库存量
  6. 评价数量

(2)将爬取的结果保存到csv文件中。

8.2 页面分析

  页面分析工具:

  1. Chrome开发者工具
  2. 常用的工具: scrapy shell 命令

    它使用户可以在交互式命令行下操作一个Scrapy爬虫,通常利用该工具进行前期爬取实验,从而提高开发效率。
    接下来分析第一本书的页面,以页面的url地址为参数运行scrapy shell命令:

(Project1) F:\pycharm_workplace\example1>scrapy shell http://books.toscrape.com/catalogue/a-light-in-the-atti
c_1000/index.html
2021-11-15 14:39:18 [scrapy.utils.log] INFO: Scrapy 2.4.1 started (bot: example1)
2021-11-15 14:39:18 [scrapy.utils.log] INFO: Versions: lxml 4.6.3.0, libxml2 2.9.12, cssselect 1.1.0, parsel
1.5.2, w3lib 1.21.0, Twisted 21.2.0, Python 3.7.11 (default, Jul 27 2021, 09:46:33) [MSC v.1916 32 bit (Intel
)], pyOpenSSL 20.0.1 (OpenSSL 1.1.1l  24 Aug 2021), cryptography 3.4.7, Platform Windows-7-6.1.7600
2021-11-15 14:39:18 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.selectreactor.SelectReactor
2021-11-15 14:39:18 [scrapy.crawler] INFO: Overridden settings:
{'BOT_NAME': 'example1',
 'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter',
 'FEED_EXPORT_ENCODING': 'utf-8-sig',
 'LOGSTATS_INTERVAL': 0,
 'NEWSPIDER_MODULE': 'example1.spiders',
 'ROBOTSTXT_OBEY': True,
 'SPIDER_MODULES': ['example1.spiders']}
2021-11-15 14:39:18 [scrapy.extensions.telnet] INFO: Telnet Password: 9c89067d6ebe79d8
2021-11-15 14:39:18 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
 'scrapy.extensions.telnet.TelnetConsole']
2021-11-15 14:39:21 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
 'scrapy.downloadermiddlewares.retry.RetryMiddleware',
 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
 'scrapy.downloadermiddlewares.stats.DownloaderStats']
2021-11-15 14:39:21 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
 'scrapy.spidermiddlewares.referer.RefererMiddleware',
 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
 'scrapy.spidermiddlewares.depth.DepthMiddleware']
2021-11-15 14:39:22 [scrapy.middleware] INFO: Enabled item pipelines:
['example1.pipelines.DuplicatesPipeline']
2021-11-15 14:39:22 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6024
2021-11-15 14:39:22 [scrapy.core.engine] INFO: Spider opened
2021-11-15 14:39:23 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://books.toscrape.com/robots.txt> (ref
erer: None)
2021-11-15 14:39:23 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://books.toscrape.com/catalogue/a-ligh
t-in-the-attic_1000/index.html> (referer: None)
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x053237B0>
[s]   item       {}
[s]   request    <GET http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html>
[s]   response   <200 http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html>
[s]   settings   <scrapy.settings.Settings object at 0x0531F310>
[s]   spider     <DefaultSpider 'default' at 0x5888770>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
>>>

    运行这条命令后,scrapy shell会使用url参数构造一个Request对象,并提交给Scrapy引擎,页面下载完成后,程序进入一个python shell当中,在此环境中已经创建好了一些变量(对象和函数),以下几个最为常用:
● request
    最近一次下载对应的Request对象。
● response
    最近一次下载对应的Response对象。
● fetch(req_or_url)
    该函数用于下载页面,可传入一个Request对象或url字符串,调用后会更新变量request和response。
● view(response)
    该函数用于在浏览器中显示response中的页面。
    接下来,在scrapy shell中调用view函数,在浏览器中显示response所包含的页面:

>>> view(response)

    可能在很多时候,使用view函数打开的页面和在浏览器直接输入url打开的页面看起来是一样的,但需要知道的是,前者是由Scrapy爬虫下载的页面,而后者是由浏览器下载的页面,有时它们是不同的。在进行页面分析时,使用view函数更加可靠。
    下面使用Chrome审查元素工具分析页面:
图1

    在 < div class=“col-sm-6 product_main”>中提取书名、价格、评价等级,在scrapy shell中尝试提取这些信息。

>>> sel = response.css('div.product_main')
>>> sel.xpath('./h1/text()').extract_first()
'A Light in the Attic'
>>> sel.css('p.price_color::text').extract_first()
'£51.77'
>>> sel.css('p.star-rating::attr(class)').re_first('star-rating ([A-Za-z]+)')
'Three'

  另外,可在页面下端位置的< table class=“table table-striped”>中提取产品编码、库存量、评价数量,在scrapy shell中尝试提取这些信息:

#尝试提取table中各标签文本
>>> sel = response.css('table.table.table-striped')
#或者只用一个class
>>> sel =response.css('table.table')
#table中各个标签名称
>>> sel.xpath('.//tr/th/text()').extract()
['UPC', 'Product Type', 'Price (excl. tax)', 'Price (incl. tax)', 'Tax', 'Availability', 'Number of reviews']

#提取产品编号(upc)及具体编号
>>> sel.xpath('.//tr/th/text()').extract()[0]
'UPC'
>>> sel.xpath('.//tr/th/text()').extract_first()
'UPC'
>>> sel.xpath('.//tr/td/text()').extract_first()
'a897fe39b1053632'
>>> sel.xpath('(.//tr)/td/text()').extract()[0]
'a897fe39b1053632'
>>> sel.xpath('(.//tr)[1]/td/text()').extract_first()
'a897fe39b1053632'

#提取库存数
>>> sel.xpath('(.//tr)[last()-1]/td/text()')
[<Selector xpath='(.//tr)[last()-1]/td/text()' data='In stock (22 available)'>]
>>> sel.xpath('(.//tr)[last()-1]/td/text()').extract()
['In stock (22 available)']
>>> sel.xpath('(.//tr)[last()-1]/td/text()').extract()[0]
'In stock (22 available)'
>>> sel.xpath('(.//tr)/td/text()[-2]').extract()#不能提取
[]

>>> sel.xpath('(.//tr)/td/text()')[-2].extract()# 可以提取
'In stock (22 available)'
>>> sel.xpath('(.//tr)[last()-1]/td/text()').re_first('\((\d+) available\)')
'22'
>>> sel.xpath('(.//tr)/td/text()')[-2].re_first('\((\d+) available\)')
'22'
#提取评价数量
>>> sel.xpath('(.//tr)/td/text()')[-1]
<Selector xpath='(.//tr)/td/text()' data='0'>
>>> sel.xpath('(.//tr)/td/text()')[-1].extract()
'0'

   分析完书籍页面后,接着分析如何在书籍列表页面中提取每一个书籍页面的链接
   在scrapy shell中,先调用fetch函数下载第一个书籍列表页面(http://books.toscrape.com/),下载完成后再调用view函数在浏览器中查看页面。

>>> fetch('http://books.toscrape.com/')
2021-11-15 17:11:43 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://books.toscrape.com/> (referer: None)

   每个书籍页面的链接可以在每个< article class=“product_pod”>中找到,在scrapy shell中使用LinkExtractor提取这些链接:

>>> view(response)
True
>>> from scrapy.linkextractors import LinkExtractor
>>> le = LinkExtractor(restrict_css='article.product_pod')
>>> le.extract_links(response)
[Link(url='http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/soumission_998/index.html', text=''
, fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/sharp-objects_997/index.html',
text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/sapiens-a-brief-history-
of-humankind_996/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/the-requiem-red_995/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/the-dirty-little-secrets-of-getting-your-dream-job_994/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/the-coming-woman-a-novel-based-on-the-life-of-the-infamous-feminist-victoria-woodhull_993/index.html', text='', fragment='', nofollow=False),
Link(url='http://books.toscrape.com/catalogue/the-boys-in-the-boat-nine-americans-and-their-epic-quest-for-gold-at-the-1936-berlin-olympics_992/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/the-black-maria_991/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/starving-hearts-triangular-trade-trilogy-1_990/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/set-me-free_988/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/scott-pilgrims-precious-little-life-scott-pilgrim-1_987/index.html', text='', fragment='', nofollow=False), Link(url='http://books.toscrape.com/catalogue/rip-it-up-and-start-again_986/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/our-band-could-be-your-life-scenes-from-the-american-indie-underground-1981-1991_985/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/olio_984/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/mesaerion-the-best-science-fiction-stories-1800-1849_983/index.html', text='', fragment='', nofollow=False), 
Link(url='http://books.toscrape.com/catalogue/libertarianism-for-beginners_982/index.html', text='', fragment='', nofoll
ow=False), 
Link(url='http://books.toscrape.com/catalogue/its-only-the-himalayas_981/index.html', text='', fragment='', nofollow=False)]
>>>

  到此,页面分析的工作已经完成了。

8.3 编码实现

  首先创建一个Scrapy项目,取名为toscrape_book。

$ scrapy startproject toscrape_book

  通常,我们不需要手工创建Spider文件以及Spider类,可以使用scrapy genspider< SPIDER_NAME> < DOMAIN>命令生成(根据模板)它们,该命令的两个参数分别是Spider的名字和所要爬取的域(网站):

$ cd toscrape_book
$ scrapy genspider books books.toscrape.com

  运行后,scrapy genspider命令创建了文toscrape_book/spiders/books.py,并在其中创建了一个BooksSpider类
图2
  定义封装书籍信息的Item类,在toscrape_book/items.py中添加如下代码:
图3
  完成BooksSpider ,5步骤。
步骤 01 继承Spider创建BooksSpider类(已完成)。
步骤 02 为Spider取名(已完成)。
步骤 03 指定起始爬取点(已完成)。
步骤 04 实现书籍列表页面的解析函数。
步骤 05 实现书籍页面的解析函数。

  前3步已经由scrapy genspider命令帮我们完成,
  第4步和第5步的工作是实现两个页面解析函数,因为起始爬取点是一个书籍列表页面,将parse方法作为书籍列表页面的解析函数(第4步),添加一个parse_book方法作为书籍页面的解析函数(第5步),代码如下:

图5
  先来完成第4步,实现书籍列表页面的解析函数(parse方法),需要完成以下两个任务:
(1)提取页面中每一个书籍页面的链接,用它们构造Request对象并提交。
(2)提取页面中下一个书籍列表页面的链接,用其构造Request对象并提交。
  提取链接的具体细节在页面分析时已经讨论过,实现代码如下:
图6
  最后完成第5步,实现书籍页面的解析函数(parse_book方法),只需提取书籍信息存入BookItem对象即可。最终完成代码如下:
图7
  注:书中是利用xpath中的last()函数提取table中的属性,其实根据list的属性可以用位置标号查找确定相关数据
  运行观察:

$ scrapy crawl books -o books.csv --nolog

  运行后,打开books.csv文件
图8
  以上可以爬取1000条数据,但有两个问题:

(1)csv文件中各列的次序是随机的,看起来比较混乱.
可在配置文件settings.py中使用FEED_EXPORT_FIELDS指定各列的次序:

FEED_EXPORT_FIELDS = ['upc', 'name', 'price', 'stock', 'review_rating', 'review_num']

(2)结果中评价等级字段的值是One、Two、Three……这样的单词,而不是阿拉伯数字,阅读起来不是很直观。
    下面实现一个ItemPipeline,将评价等级字段由单词映射到数字(或许这样简单的需求使用Item Pipeline有点大材小用,但可以复习之前所学的知识)。
在pipelines.py中实现BookPipeline,代码如下:

class BookPipeline(object):
review_rating_map = {
'One': 1,
'Two': 2,
'Three': 3,
'Four': 4,
'Five': 5,
}
def process_item(self, item, spider):
rating = item.get('review_rating')
if rating:
item['review_rating'] = self.review_rating_map[rating]
return item

   注意:review_rating_map的key需要和爬取的英语一致,首字母大写,不然会出现key_error

    在配置文件settings.py中启用BookPipeline:

ITEM_PIPELINES = {
'toscrape_book.pipelines.BookPipeline': 300,
}

    运行爬虫,并观察结果:

$ scrapy crawl books -o books1.csv

图9
    字段已排序,评价等级为阿拉伯数字。

8.4 小结

    通过熟悉 scrapy shell及相关方法的使用解析页面,已经初步熟悉提取的方法;并依据书中的项目流程完成了数据提取下载,仍需要对xpath、css方法以及linkextractorf方法的相关内容进一步熟悉。

    本文参照《精通Scrapy网络爬虫+(刘硕著)》PDF,并自己跑相关代码,代码内容稍作修改,仅做参考和笔记复习使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建Scrapy项目的步骤如下: 1. **安装Scrapy**: 首先需要确保已经安装了Python环境。然后可以在命令行中输入以下命令来安装Scrapy: ``` pip install scrapy ``` 2. **创建新项目**: 打开命令行界面,切换到你想存放项目的目录下,运行以下命令来创建一个新的Scrapy项目: ``` scrapy startproject your_project_name ``` 这里`your_project_name`是你给新项目起的名字。 3. **进入项目目录**: 切换到刚刚创建的项目文件夹: ``` cd your_project_name ``` 4. **运行爬虫**: 在项目目录内,你可以开始创建爬虫。首先创建一个爬虫文件,例如命名为 `example_spider.py`: ``` touch example_spider.py ``` 然后打开并编辑这个文件。在里面编写爬取规则、解析规则等。Scrapy的文档中有详细的示例和指南,可以帮助你快速上手。 5. **配置爬虫**: 如果你需要自定义一些配置信息,可以修改项目的 `settings.py` 文件。在这个文件中,你可以设置代理、下载中间件、错误处理等选项。 6. **启动爬虫**: 在项目根目录中,启动你的爬虫: ``` scrapy crawl example_spider ``` 按照提示输入需要爬取的URL或者其他相关信息,然后观察日志查看爬虫执行情况。 7. **管理数据**: Scrapy会自动将爬取的数据存储在指定的位置,如 `items.json` 或 `items.csv` 等。你可以自定义存储格式或位置。 8. **调试与优化**: 在实际操作过程中,可能会遇到各种问,如页面加载慢、反爬策略等。这时需要对爬虫进行调试,并根据需求进行优化。 通过以上步骤,你就可以成功地创建并运行一个基于Scrapy框架的网页爬虫项目了。记住查阅Scrapy官方文档获取更多详细信息和最佳实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值