在Python中开发您的第一个Web爬虫

什么是Scrapy?

维基百科

Scrapy(/skreɪpi/ skray-pee)

[1]是一个免费的开放源代码的网页爬虫框架,用Python编写。最初设计用于网页抓取,它也可以用于使用API​​提取数据或作为通用网络爬虫。

[2] 它目前由Scrapinghub Ltd.,一家网络搜索开发和服务公司维护。

一个网络爬行框架,完成了编写爬虫所需的所有繁重工作。那些东西是什么,我会在下面进一步探讨。

请继续阅读!

创建项目

Scrapy 在单个项目中引入了包含多个crawlers或 spiders的项目。如果您正在为站点的不同部分或站点的子域编写多个爬网程序,此概念特别有用。所以,首先创建该项目

Adnans-MBP:ScrapyCrawlers AdnanAhmad$ scrapy startproject olx
New 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的项目并为后续步骤提供有用的信息。您转到新创建的文件夹,然后执行命令以生成名称和要爬网的站点的域名的第一个spiders

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

我用名字电子产生了我的第一个spiders的代码,因为我正在访问OLX的电子部分,我将它命名为这样,你可以将它命名为任何你想要的或者将你的第一只spiders奉献给你的配偶或(女孩)朋友:>

最终的项目结构将如下所示:

在Python中开发您的第一个Web爬虫

正如你所看到的,只有spiders才有单独的文件夹,如前所述,你可以在一个项目中添加多个spiders。让我们打开electronics.py spiders文件。当你打开它时,你会发现这样的东西:

在Python中开发您的第一个Web爬虫

正如你所看到的,ElectronicsSpider是的子类scrapy.Spider。该name属性实际上是spider生成命令中给出的spider的名称。这个名字将有助于运行爬虫本身。该allowed_domains属性告诉哪些域可供该爬虫访问,并且strart_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)

为了使抓取工具导航到很多页面,我宁愿将抓取工具从Crawler而不是scrapy.Spider中分类。这个类使得爬行网站的许多页面更容易。你可以用生成的代码做类似的事情,但你需要注意递归来浏览下一页。

接下来是设置规则变量,这里您提到导航网站的规则。LinkExtractor实际上需要参数来绘制导航边界。这里我使用restrict_css参数来为NEXT页面设置类。如果你去这个页面并检查元素,你可以找到这样的东西:

在Python中开发您的第一个Web爬虫

pageNextPrev是用于获取下一页链接的类。该call_back参数告诉用哪个方法来访问页面元素。我们很快就会研究这个方法。

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

到目前为止,我们来测试我迄今为止所做的抓取工具。再次,去终端并写下:

Adnans-MBP:olx AdnanAhmad$ scrapy crawl electronics

第三个参数实际上是在类的name属性中早先设置的spider的名称ElectronicsSpiders。在控制台上您会发现很多有用的信息,这些信息对调试爬虫有帮助。如果您不想查看调试信息,可以禁用调试器。该命令与--nolog开关类似。

Adnans-MBP:olx AdnanAhmad$ 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,抓取工具将检查下一页的规则,并将继续导航,除非它遇到规则不表示的页面,通常是列表的最后一页。现在想象一下,如果我要用这里提到的东西编写类似的逻辑,首先我必须编写代码来产生多个进程,我还必须编写代码来导航下一页,但也限制我的脚本停留在边界之内没有访问不需要的URL,Scrapy将这一切从我的肩膀上解放出来,并使我专注于主要逻辑,即编写爬取器来提取信息。

现在我要编写将从列表页面获取单个项目链接的代码。我将在parse_item方法中修改代码。

在Python中开发您的第一个Web爬虫

在这里我通过使用.css响应方法来获取链接 。正如我所说,你也可以使用xpath,取决于你。在这种情况下,它非常简单:

在Python中开发您的第一个Web爬虫

锚链接有一个类detailsLink,如果我只使用response.css('.detailsLink')它,那么由于重复链接img和h3标签,它将选择单个条目的重复链接。我做了什么,我也引用了父类large,以获得独特的链接。我也习惯 ::attr(href)提取href链接本身的部分。我然后使用extract()方法。使用的原因是, .css并 .xpath返回SelectorList对象,extract()有助于返回实际的DOM进一步处理。最后,我正在与回调yield链接scrapy.Request。我没有检查Scrapy的内部代码,但很可能他们正在使用yield而不是areturn因为您可以产生多个项目,并且由于爬虫需要一起照顾多个链接,因此yield这里是最佳选择。

parse_detail_page名称告知的方法是解析详细信息页面中的个人信息。所以实际发生的是:

· 您可以获得参赛作品列表 parse_item

· 通过回调方法将它们传递给进一步处理。

由于这只是一个两级的遍历,我能够在两种方法的帮助下达到最低级别。如果我要开始从OLX的主页爬行,我将不得不在这里写3种方法; 前两个取得子类别及其条目,最后一个解析实际信息。明白了我的观点?

最后,我要解析的实际信息,您可在喜欢的一个条目这一个

从这个页面解析信息并没有什么不同,但是这里有一些工作要存储已解析的信息。我们需要为我们的数据定义模型。这意味着我们需要告诉Scrapy我们想要存储什么信息供以后使用。让我们编辑item.pyScrapy早先生成的文件。

import scrapy
class OlxItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass

OlxItem是我将在其中设置必填字段以保存信息的班级。我将为我的模型类定义3个字段。

class OlxItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field()
price = scrapy.Field()
url = scrapy.Field()

我将存储帖子的标题,价格和网址本身。让我们回到爬虫类并修改parse_detail_page。现在有一种方法是开始编写代码,通过运行整个爬虫程序来测试,并确定您是否在正确的轨道上,但还有另一个由Scrapy提供的令人敬畏的工具。

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格式获取数据,所有你需要做的就是通过json与-t开关。

还有一件事,Scrapy为您提供了另一个功能,通过一个固定的文件名在现实世界的场景中没有任何意义,我怎么能有一些工具来生成独特的文件名?那么,你需要修改settings.py文件并添加这两个条目:

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

在这里,我给出了我的文件的模式,%(name)%是履带本身的名称,并且time是时间戳。你可以在这里进一步了解它。现在,当我运行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"},
...
]

结论

我打算在未来几天内提出一些其他技术。敬请关注!


分享到:


相關文章: