scrapy分页抓取网页(牛津小马哥web前端工程师陈小妹妹(之前)(图) )

优采云 发布时间: 2022-04-19 16:44

  scrapy分页抓取网页(牛津小马哥web前端工程师陈小妹妹(之前)(图)

)

  原创:陈晓梅,Oxford Pony Brothers Web 前端工程师。

  

  在本文中,我将编写一个网络爬虫,从 OLX 的电子和电器项目中抓取数据。但在我进入代码之前,这里先简要介绍一下 Scrapy 本身。

  什么是刮痧?

  Scrapy(发音为 Scrapy)是一个用 Python 编写的开源网络爬虫框架。最初是为网页抓取而设计的。目前由 Scrapinghub 维护。

  >>>>

  创建一个项目。

  Scrapy的一个设计思路是一个项目可以收录多个爬虫。这种设计很有用,尤其是在为站点或子域的不同部分编写多个机器人时。所以首先创建项目:

  Adnans-MBP:ScrapyCrawlers AdnanAhmad$ scrapy startproject olxNew

Scrapy project 'olx', using template directory '//anaconda/lib/python2.7/site-packages/scrapy/templates/project', created in:

/Development/PetProjects/ScrapyCrawlers/olx

You can start your first spider with:

cd olx

scrapy genspider example example.com

  >>>>

  创建爬虫

  我运行了命令 scrapy startproject olx,它将创建一个名为 olx 的项目。接下来,进入新创建的文件夹,执行命令生成第一个爬虫,并带有要爬取的站点的名称和域:

  Adnans-MBP:ScrapyCrawlers AdnanAhmad$ cd olx/

Adnans-MBP:olx AdnanAhmad$ scrapy genspider electronics www.olx.com.pk

Created spider 'electronics' using template 'basic' in module:

olx.spiders.electronics

  下面是 OLX 的“电子”文件部分,最终的项目结构将类似于以下示例:

  

  如您所见,这个新创建的爬虫有一个单独的文件夹。您可以将多个爬虫添加到一个项目中。让我们打开爬虫文件electronics.py。当您打开它时,您将看到以下内容:

  # -*- coding: utf-8 -*-

import scrapy

class ElectronicsSpider(scrapy.Spider):

name = "electronics"

allowed_domains = ["www.olx.com.pk"]

start_urls = ['http://www.olx.com.pk/']

def parse(self, response):

pass

  如您所见,ElectronicsSpider 是 scrapy.Spider 的子类。name 属性其实就是蜘蛛的名字,在spider中指定。allowed_domains 属性告诉我们这个爬虫可以访问哪些域,start_urls 位置是需要首先访问初始 URL 的位置。

  parse 顾名思义,这个方法会解析被访问页面的内容。由于我想写一个爬虫到多个页面,我会做一些改变。

  from scrapy.spiders import CrawlSpider, Rule

from scrapy.linkextractors import LinkExtractor

class ElectronicsSpider(CrawlSpider):

name = "electronics"

allowed_domains = ["www.olx.com.pk"]

start_urls = [

'https://www.olx.com.pk/computers-accessories/',

'https://www.olx.com.pk/tv-video-audio/',

'https://www.olx.com.pk/games-entertainment/'

]

rules = (

Rule(LinkExtractor(allow=(), restrict_css=('.pageNextPrev',)),

callback="parse_item",

follow=True),)

def parse_item(self, response):

print('Processing..' + response.url)

  为了让爬虫导航到多个页面,我从 scrapy.Spider 子类化为 CrawlSpider。这个类可以更容易地抓取 网站 的许多页面。您可以对生成的代码执行类似的操作,但您需要小心递归以导航下一页。

  下一步是设置规则变量。在这里可以设置浏览网站的规则。在 LinkExtractor 中设置一些导航限制。这里我使用restrict_css参数来设置NEXT页面的类。如果您转到此页面并检查元素,您可以找到以下内容:

  

  pageNextPrev 是用于获取下一页链接的类。call_back 参数告诉使用哪种方法来访问页面元素。

  请记住,您需要将方法的名称从 parse() 更改为 parse_item() 或其他名称,以避免覆盖基类,否则即使您设置 follow=True ,您的规则也将不起作用。

  到现在为止还挺好; 让我们测试一下到目前为止我们制作的爬虫。转到终端,在项目目录中输入:

  scrapy crawl electronics

  第三个参数其实是蜘蛛的名字,ElectronicsSpiders,之前在类名属性中设置的。在终端中,您会发现许多有助于调试的有用信息。如果不想看到调试信息,可以禁用调试器。此命令类似于 --nologswitch。

  scrapy crawl --nolog electronics

  如果现在运行,它将显示以下内容:

  Adnans-MBP:olx AdnanAhmad$ scrapy crawl --nolog electronics

Processing..https://www.olx.com.pk/computers-accessories/?page=2

Processing..https://www.olx.com.pk/tv-video-audio/?page=2

Processing..https://www.olx.com.pk/games-entertainment/?page=2

Processing..https://www.olx.com.pk/computers-accessories/

Processing..https://www.olx.com.pk/tv-video-audio/

Processing..https://www.olx.com.pk/games-entertainment/

Processing..https://www.olx.com.pk/computers-accessories/?page=3

Processing..https://www.olx.com.pk/tv-video-audio/?page=3

Processing..https://www.olx.com.pk/games-entertainment/?page=3

Processing..https://www.olx.com.pk/computers-accessories/?page=4

Processing..https://www.olx.com.pk/tv-video-audio/?page=4

Processing..https://www.olx.com.pk/games-entertainment/?page=4

Processing..https://www.olx.com.pk/computers-accessories/?page=5

Processing..https://www.olx.com.pk/tv-video-audio/?page=5

Processing..https://www.olx.com.pk/games-entertainment/?page=5

Processing..https://www.olx.com.pk/computers-accessories/?page=6

Processing..https://www.olx.com.pk/tv-video-audio/?page=6

Processing..https://www.olx.com.pk/games-entertainment/?page=6

Processing..https://www.olx.com.pk/computers-accessories/?page=7

Processing..https://www.olx.com.pk/tv-video-audio/?page=7

Processing..https://www.olx.com.pk/games-entertainment/?page=7

  由于我设置了follow=True,爬虫会检查NEXT页面的规则,并继续导航,直到到达不满足规则的页面,通常是列表的最后一页。

  Scrapy 解除了编写爬虫的所有任务,让我可以专注于主要逻辑,通过编写爬虫来提取信息。

  现在,我将继续编写代码以从列表页面获取单个项目链接。我将在 parse_item 方法中对其进行修改。

  item_links = response.css('.large > .detailsLink::attr(href)').extract()

for a in item_links:

yield scrapy.Request(a, callback=self.parse_detail_page)

  在这里,我使用 .css 响应方法获取链接。您也可以使用 xpath,这取决于您。在这种情况下,它非常简单:

  

  锚链接有一个类 detailsLink。如果您只使用 response.css('.detailsLink'),由于 img 和 h3 标签中的重复链接,它将为单个条目选择重复链接。我还提到了用于唯一链接的大型父类。我之前提取的 href 部分 ::attr(href) 是链接本身。然后,我使用 extract() 方法。

  使用此方法的原因是 .css 和 .xpath 返回 SelectorList 对象,而 extract() 有助于返回实际的 DOM 以供进一步处理。最后,我在 scrapy.Request 回调中收录了 yield 链接。我没有检查 Scrapy 的内部代码,但很可能他们使用的是 yield 而不是 A, return 因为你可以生产多个项目。由于爬虫需要同时处理多个链接,因此 yield 是这里的最佳选择。

  parse_detail_page 顾名思义,这个方法会解析详情页中的个体信息。所以实际发生的是:

  您将获得 parse_item 中的项目列表。

  您将它们传递给回调方法以进行进一步处理。

  由于它只是一个两层遍历,我可以借助两种方法到达最低层。如果要从OLX主页开始爬,这里要写三个方法:前两个获取子类及其条目,最后一个解析实际信息。知道了?

  最后,我将解析实际信息,这些信息可以在与此类似的项目中找到。

  解析此页面中的信息没有什么不同,但需要一些操作来存储解析的信息。我们需要为数据定义一个模型。这意味着我们需要告诉 Scrapy 我们想要存储哪些信息以供以后使用。让我们编辑之前由 Scrapy 生成的 item.py 文件。

  import scrapy

class OlxItem(scrapy.Item):

# define the fields for your item here like:

# name = scrapy.Field()

pass

  OlxItem 我将设置所需字段以保存信息的类。我将为模型类定义三个字段。

  class OlxItem(scrapy.Item):

# define the fields for your item here like:

title = scrapy.Field()

price = scrapy.Field()

url = scrapy.Field()

  我将存储帖子的标题、价格和 URL 本身。

  让我们回到爬虫类,修改parse_detail_page。

  现在,一种方法是开始编写代码,通过运行整个爬虫来测试它,看看你是否走在正确的轨道上,但是 Scrapy 提供了另一个很棒的工具。

  >>>>

  废壳

  Scrapy Shell 是一个命令行工具,允许您在不运行整个爬虫的情况下测试解析代码。与访问所有链接的爬虫不同,Scrapy Shell 保存单个页面的 DOM 以进行数据提取。就我而言,我做了以下事情:

  Adnans-MBP:olx AdnanAhmad$ scrapy shell https://www.olx.com.pk/item/asus-eee-pc-atom-dual-core-4cpus-beautiful-laptops-fresh-stock-IDUVo6B.html#4001329891

  现在我可以轻松地测试代码,而不必一次又一次地访问相同的 URL。我这样做是为了获得标题:

  In [8]: response.css('h1::text').extract()[0].strip()

Out[8]: u"Asus Eee PC Atom Dual-Core 4CPU's Beautiful Laptops fresh Stock"

  您可以在 response.css 中找到熟悉的内容。由于整个 DOM 都可用,因此您可以使用它。

  我通过这样做得到价格:

  In [11]: response.css('.pricelabel > strong::text').extract()[0]

Out[11]: u'Rs 10,500'

  由于 response.url 返回的是当前访问的 URL,所以不需要做任何事情来获取 url。

  现在已经检查了所有代码,是时候将其合并到 parse_detail_page 中了:

  title = response.css('h1::text').extract()[0].strip()

price = response.css('.pricelabel > strong::text').extract()[0]

item = OlxItem()

item['title'] = title

item['price'] = price

item['url'] = response.url

yield item

  解析所需信息后,OlxItem 将创建实例并设置属性。现在是时候运行爬虫并存储信息了,对命令进行了一些修改:

  scrapy crawl electronics -o data.csv -t csv

  我正在传递文件名和文件格式来保存数据。运行后,它将为您生成 CSV。很简单,不是吗?与您自己编写的爬虫不同,您必须编写自己的例程来保存数据。

  可是等等!它并不止于此,您甚至可以获取 JSON 格式的数据。您所要做的就是使用 -t 开关传递 json。

  Scrapy 为您提供了另一个功能。在实际情况下,传递一个固定的文件名没有任何意义。如何生成唯一的文件名?好吧,为此,您需要修改 settings.py 文件并添加以下两个条目:

  FEED_URI = 'data/%(name)s/%(time)s.json'

FEED_FORMAT = 'json'

  这里我给出文件的模式,%(name)% 是爬虫本身的名字和时间戳。你可以在这里了解更多。现在,当我运行 scrapy crawl --nolog electronics 或 scrapy crawl electronics 时,它会在 data 文件夹中生成一个 JSON 文件,如下所示:

  [

{"url": "https://www.olx.com.pk/item/acer-ultra-slim-gaming-laptop-with-amd-fx-processor-3gb-dedicated-IDUQ1k9.html", "price": "Rs 42,000", "title": "Acer Ultra Slim Gaming Laptop with AMD FX Processor 3GB Dedicated"},

{"url": "https://www.olx.com.pk/item/saw-machine-IDUYww5.html", "price": "Rs 80,000", "title": "Saw Machine"},

{"url": "https://www.olx.com.pk/item/laptop-hp-probook-6570b-core-i-5-3rd-gen-IDUYejF.html", "price": "Rs 22,000", "title": "Laptop HP Probook 6570b Core i 5 3rd Gen"},

{"url": "https://www.olx.com.pk/item/zong-4g-could-mifi-anlock-all-sim-supported-IDUYedh.html", "price": "Rs 4,000", "title": "Zong 4g could mifi anlock all Sim supported"},

...

]

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线