Python版本管理:pyenv與pyenv-virtualenv
Scrapy爬蟲入門教學一安裝和基本使用
Scrapy爬蟲入門教學二官方提供Demo
Scrapy爬蟲入門教學三命令列工具介紹和範例
Scrapy爬蟲入門教學四Spider(爬蟲)
Scrapy爬蟲入門教學五Selectors(選擇器)
Scrapy爬蟲入門教學六Items(專案)
Scrapy爬蟲入門教學七Item Loaders(專案載入器)
Scrapy爬蟲入門教學八互動shell 方便調試
Scrapy爬蟲入門教學九Item Pipeline(專案管道)
Scrapy爬蟲入門教學十Feed exports(匯出檔案)
Scrapy爬蟲入門教學十一Request和Response(請求與回應)
Scrapy爬蟲入門教學十二Link Extractors(連結擷取器)
[toc]
開發環境:Python 3.6.0 版本
(目前最新) Scrapy 1.3.2 版本
(目前最新)
爬蟲是定義如何抓取某個網站(或一組網站)的類,包括如何執行抓取(即關注連結)以及如何從其網頁中提取結構化資料(即抓取項目)。句話說,Spider是您定義用於為特定網站(或在某些情況下,一組網站)抓取和解析網頁的自訂行為的位置。 ,
循環。 parse方法獲取, 並且該方法作為請求的回調函數。物件, Request物件或這些物件的可迭代的物件。
ulSoup,l即使這個循環(或多或少)適用於任何種類的爬蟲,有不同種類的預設爬蟲捆綁到Scrapy中用於不同的目的。我們將在這裡談論這些類型。
classstart_requests()
實現,它從<a href="http://www.php.cn/wiki/164.html" target="_blank">屬性</a>發送請求,並
parsespider的方法。 name
定義此爬蟲名稱的字串。爬蟲名稱是爬蟲如何由Scrapy定位(和實例化),因此它
必須是唯一的
。但是,沒有什麼能阻止你實例化同一個爬蟲的多個實例。這是最重要的爬蟲屬性,它是必要的。 如果爬蟲抓取單一域名,通常的做法是在網域後面命名爬蟲。因此,例如,抓取的爬蟲mywebsite.com通常會被呼叫 mywebsite。
注意
在Python 2中,這必須是ASCII。 allowed_domain
其它就不會抓取了。
當沒有指定特定網址時,爬蟲將開始抓取的網址清單。 <a href="http://www.php.cn/wiki/646.html" target="_blank"><p><code>custom_<a href="http://www.php.cn/code/8209.html" target="_blank">set</a>tings
在執行此爬蟲時將從項目寬配置覆蓋的設定字典。它必須定義為類別屬性,因為設定在實例化之前更新。
有關可用內建設定的列表,請參閱: 內建設定參考。
crawler
此屬性from_crawler()在初始化類別後由類別方法設置,並連結Crawler到此爬蟲實例綁定到的物件。
Crawlers在專案中封裝了許多元件,用於單一條目存取(例如擴展,中間件,訊號管理器等)。有關詳情,請參閱抓取工具API。
settings
執行此爬蟲的配置。這是一個 Settings實例,有關此主題的詳細介紹,請參閱設定主題。
logger
用Spider建立的Python記錄器name
。您可以使用它透過它發送日誌訊息,如記錄爬蟲程序中所述。
from_crawler
(crawler, args,* kwargs )
是Scrapy用來建立爬蟲的類別方法。
您可能不需要直接覆寫這一點,因為預設實作充當方法的代理,init()
使用給定的參數args和命名參數kwargs呼叫它。
儘管如此,此方法 在新實例中設定crawler和settings屬性,以便以後可以在爬蟲程式中存取它們。
參數:
crawler(Crawlerinstance) - 爬蟲將綁定到的爬蟲
#args(list) - 傳遞給init()方法的參數
#kwargs(dict) - 傳遞給init()方法的關鍵字參數
start_requests()
此方法必須傳回一個可迭代的第一個請求來抓取這個爬蟲。
有了start_requests(),就不寫了start_urls,寫了也沒用。
預設實作是:start_urls,但是可以複寫的方法start_requests。
例如,如果您需要透過使用POST請求登入來啟動,您可以:
class MySpider(scrapy.Spider): name = 'myspider' def start_requests(self): return [scrapy.FormRequest("http://www.example.com/login", formdata={'user': 'john', 'pass': 'secret'}, callback=self.logged_in)] def logged_in(self, response): # here you would extract links to follow and return Requests for # each of them, with another callback pass
make_requests_from_url(url)
#一種接收URL並傳回Request 物件(或Request物件清單)進行抓取的方法。此方法用於在方法中建構初始請求 start_requests(),並且通常用於將URL轉換為請求。
除非重寫,此方法會傳回具有方法的Requests parse() 作為它們的回調函數,並啟用dont_filter參數(Request有關更多信息,請參閱類別)。
parse(response)
這是Scrapy用於處理下載的回應的預設回調,當它們的請求沒有指定回調時。
該parse方法負責處理回應並傳回所抓取的資料或更多的URL。其他請求回呼具有與Spider類別相同的要求。
此方法以及任何其他請求回呼必須傳回一個可迭代的Request和dicts或Item物件。
參數:
response(Response) - 解析的回應
##log(message[, level, component])包裝器透過爬蟲發送日誌訊息logger,保持向後相容性。有關詳細信息,請參閱 從Spider記錄。
closed(reason)
當爬蟲關閉時召喚。此方法為spider_closed訊號的signals.connect()提供了一個捷徑。讓我們來看一個例子:
import scrapy class MySpider(scrapy.Spider): name = 'example.com' allowed_domains = ['example.com'] start_urls = [ 'http://www.example.com/1.html', 'http://www.example.com/2.html', 'http://www.example.com/3.html', ] def parse(self, response): self.logger.info('A response from %s just arrived!', response.url)
import scrapy class MySpider(scrapy.Spider): name = 'example.com' allowed_domains = ['example.com'] start_urls = [ 'http://www.example.com/1.html', 'http://www.example.com/2.html', 'http://www.example.com/3.html', ] def parse(self, response): for h3 in response.xpath('//h3').extract(): yield {"title": h3} for url in response.xpath('//a/@href').extract(): yield scrapy.Request(url, callback=self.parse)
import scrapy from myproject.items import MyItem class MySpider(scrapy.Spider): name = 'example.com' allowed_domains = ['example.com'] def start_requests(self): yield scrapy.Request('http://www.example.com/1.html', self.parse) yield scrapy.Request('http://www.example.com/2.html', self.parse) yield scrapy.Request('http://www.example.com/3.html', self.parse) def parse(self, response): for h3 in response.xpath('//h3').extract(): yield MyItem(title=h3) for url in response.xpath('//a/@href').extract(): yield scrapy.Request(url, callback=self.parse)
import scrapy class MySpider(scrapy.Spider): name = 'myspider' def init(self, category=None, *args, **kwargs): super(MySpider, self).init(*args, **kwargs) self.start_urls = ['http://www.example.com/categories/%s' % category] # ...
import scrapy class MySpider(scrapy.Spider): name = 'myspider' def start_requests(self): yield scrapy.Request('http://www.example.com/categories/%s' % self.category)
有效的用例是设置使用的http验证凭据HttpAuthMiddleware 或用户代理使用的用户代理UserAgentMiddleware:scrapy crawl myspider -a http_user=myuser -a http_pass=mypassw<a href="http://www.php.cn/wiki/1360.html" target="_blank">ord</a> -a user_agent=mybot
Spider参数也可以通过Scrapyd schedule.jsonAPI 传递。请参阅Scrapyd文档。
Scrapy附带一些有用的通用爬虫,你可以使用它来子类化你的爬虫。他们的目的是为一些常见的抓取案例提供方便的功能,例如根据某些规则查看网站上的所有链接,从站点地图抓取或解析XML / CSV Feed。
对于在以下爬虫中使用的示例,我们假设您有一个TestItem
在myproject.items
模块中声明的项目:
import scrapy class TestItem(scrapy.Item): id = scrapy.Field() name = scrapy.Field() description = scrapy.Field()
类 scrapy.spiders.CrawlSpider
这是最常用的爬行常规网站的爬虫,因为它通过定义一组规则为下列链接提供了一种方便的机制。它可能不是最适合您的特定网站或项目,但它是足够通用的几种情况,所以你可以从它开始,根据需要覆盖更多的自定义功能,或只是实现自己的爬虫。
除了从Spider继承的属性(你必须指定),这个类支持一个新的属性:
rules
它是一个(或多个)Rule
对象的列表。每个都Rule
定义了抓取网站的某种行为。规则对象如下所述。如果多个规则匹配相同的链接,则将根据它们在此属性中定义的顺序使用第一个。
这个爬虫还暴露了可覆盖的方法:
parse_start_url(response)
对于start_urls响应调用此方法。它允许解析初始响应,并且必须返回Item
对象,Request
对象或包含任何对象的迭代器。
class scrapy.spiders.Rule(link_extractor,callback = None,cb_kwargs = None,follow = None,process_links = None,process_request = None )
link_extractor
是一个链接提取程序对象,它定义如何从每个爬网页面提取链接。
callback
是一个可调用的或字符串(在这种情况下,将使用具有该名称的爬虫对象的方法),以便为使用指定的link_extractor提取的每个链接调用。这个回调接收一个响应作为其第一个参数,并且必须返回一个包含Item和 Request对象(或它们的任何子类)的列表。
警告
当编写爬网爬虫规则时,避免使用parse
作为回调,因为CrawlSpider
使用parse
方法本身来实现其逻辑。所以如果你重写的parse
方法,爬行爬虫将不再工作。
cb_kwargs
是包含要传递给回调函数的关键字参数的dict。
follow
是一个布尔值,它指定是否应该从使用此规则提取的每个响应中跟踪链接。如果callback
是None follow
默认为True
,否则默认为False
。
process_links
是一个可调用的或一个字符串(在这种情况下,将使用具有该名称的爬虫对象的方法),将使用指定从每个响应提取的每个链接列表调用该方法link_extractor
。这主要用于过滤目的。
process_request
是一个可调用的或一个字符串(在这种情况下,将使用具有该名称的爬虫对象的方法),它将被此规则提取的每个请求调用,并且必须返回一个请求或无(过滤出请求) 。
现在让我们来看一个CrawlSpider的例子:
import scrapy from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor class MySpider(CrawlSpider): name = 'example.com' allowed_domains = ['example.com'] start_urls = ['http://www.example.com'] rules = ( # Extract links matching 'category.php' (but not matching 'subsection.php') # and follow links from them (since no callback means follow=True by default). Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))), # Extract links matching 'item.php' and parse them with the spider's method parse_item Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'), ) def parse_item(self, response): self.logger.info('Hi, this is an item page! %s', response.url) item = scrapy.Item() item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)') item['name'] = response.xpath('//td[@id="item_name"]/text()').extract() item['description'] = response.xpath('//td[@id="item_description"]/text()').extract() return item
这个爬虫会开始抓取example.com的主页,收集类别链接和项链接,用parse_item方法解析后者。对于每个项目响应,将使用XPath从HTML中提取一些数据,并将Item使用它填充。
class scrapy.spiders.XMLFeedSpider
XMLFeedSpider设计用于通过以特定节点名称迭代XML订阅源来解析XML订阅源。迭代器可以选自:iternodes,xml和html。iternodes为了性能原因,建议使用迭代器,因为xml和迭代器html一次生成整个DOM为了解析它。但是,html当使用坏标记解析XML时,使用作为迭代器可能很有用。
要设置迭代器和标记名称,必须定义以下类属性:
iterator
定义要使用的迭代器的字符串。它可以是:
'iternodes'
- 基于正则表达式的快速迭代器
'html'
- 使用的迭代器Selector。请记住,这使用DOM解析,并且必须加载所有DOM在内存中,这可能是一个大饲料的问题
'xml'
- 使用的迭代器Selector。请记住,这使用DOM解析,并且必须加载所有DOM在内存中,这可能是一个大饲料的问题
它默认为:'iternodes'
。
itertag
一个具有要迭代的节点(或元素)的名称的字符串。示例:itertag = 'product'
namespaces
定义该文档中将使用此爬虫处理的命名空间的元组列表。在 与将用于自动注册使用的命名空间 的方法。(prefix, uri)prefixuriregister_namespace()
然后,您可以在属性中指定具有命名空间的itertag 节点。
例:
class YourSpider(XMLFeedSpider): namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')] itertag = 'n:url' # ...
除了这些新的属性,这个爬虫也有以下可重写的方法:
adapt_response(response)
一种在爬虫开始解析响应之前,在响应从爬虫中间件到达时立即接收的方法。它可以用于在解析之前修改响应主体。此方法接收响应并返回响应(它可以是相同的或另一个)。
parse_node(response, selector)
对于与提供的标记名称(itertag)匹配的节点,将调用此方法。接收Selector每个节点的响应和 。覆盖此方法是必需的。否则,你的爬虫将不工作。此方法必须返回一个Item对象,一个 Request对象或包含任何对象的迭代器。
process_results(response, results)
对于由爬虫返回的每个结果(Items or Requests),将调用此方法,并且它将在将结果返回到框架核心之前执行所需的任何最后处理,例如设置项目ID。它接收结果列表和产生那些结果的响应。它必须返回结果列表(Items or Requests)。
这些爬虫很容易使用,让我们看一个例子:
from scrapy.spiders import XMLFeedSpider from myproject.items import TestItem class MySpider(XMLFeedSpider): name = 'example.com' allowed_domains = ['example.com'] start_urls = ['http://www.example.com/feed.xml'] iterator = 'iternodes' # This is actually unnecessary, since it's the default value itertag = 'item' def parse_node(self, response, node): self.logger.info('Hi, this is a <%s> node!: %s', self.itertag, ''.join(node.extract())) item = TestItem() item['id'] = node.xpath('@id').extract() item['name'] = node.xpath('name').extract() item['description'] = node.xpath('description').extract() return item
基本上我们做的是创建一个爬虫,从给定的下载一个start_urls,然后遍历每个item标签,打印出来,并存储一些随机数据Item。
class scrapy.spiders.CSVF
这个爬虫非常类似于XMLFeedSpider,除了它迭代行,而不是节点。在每次迭代中调用的方法是parse_row()。
delimiter
CSV文件中每个字段的带分隔符的字符串默认为','(逗号)。
quotechar
CSV文件中每个字段的包含字符的字符串默认为'"'(引号)。
<a href="http://www.php.cn/html/html-HEAD-2.html" target="_blank">head</a>ers
文件CSV Feed中包含的行的列表,用于从中提取字段。
parse_row(response, row)
使用CSV文件的每个提供(或检测到)标头的键接收响应和dict(表示每行)。这个爬虫还给予机会重写adapt_response和process_results方法的前和后处理的目的。
让我们看一个类似于前一个例子,但使用 CSVFeedSpider:
from scrapy.spiders import CSVFeedSpider from myproject.items import TestItem class MySpider(CSVFeedSpider): name = 'example.com' allowed_domains = ['example.com'] start_urls = ['http://www.example.com/feed.csv'] delimiter = ';' quotechar = "'" headers = ['id', 'name', 'description'] def parse_row(self, response, row): self.logger.info('Hi, this is a row!: %r', row) item = TestItem() item['id'] = row['id'] item['name'] = row['name'] item['description'] = row['description'] return item
class scrapy.spiders.SitemapSpider
SitemapSpider允许您通过使用Sitemaps发现网址来抓取网站。
它支持嵌套Sitemap和从robots.txt发现Sitemap网址 。
sitemap_urls
指向您要抓取的网址的网站的网址列表。
您还可以指向robots.txt,它会解析为从中提取Sitemap网址。
sitemap_rules
元组列表其中:(regex, callback)
regex是与从Sitemap中提取的网址相匹配的正则表达式。 regex可以是一个str或一个编译的正则表达式对象。
callback是用于处理与正则表达式匹配的url的回调。callback可以是字符串(指示蜘蛛方法的名称)或可调用的。
例如:sitemap_rules = [('/product/', 'parse_product')]
规则按顺序应用,只有匹配的第一个将被使用。
如果省略此属性,则会在parse回调中处理在站点地图中找到的所有网址。
sitemap_follow
应遵循的网站地图的正则表达式列表。这只适用于使用指向其他Sitemap文件的Sitemap索引文件的网站。
默认情况下,将跟踪所有网站地图。
sitemap_alternate_links
指定是否url应遵循一个备用链接。这些是在同一个url块中传递的另一种语言的同一网站的链接。
例如:
<url> <loc>http://example.com/</loc> <xhtml:link rel="alternate" hreflang="de" href="http://example.com/de"/> </url>
使用sitemap_alternate_linksset
,这将检索两个URL。随着 sitemap_alternate_links
禁用,只有http://example.com/将进行检索。
默认为sitemap_alternate_links
禁用。
最简单的示例:使用parse回调处理通过站点地图发现的所有网址 :
from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls = ['http://www.example.com/sitemap.xml'] def parse(self, response): pass # ... scrape item here ...
使用某个回调处理一些网址,并使用不同的回调处理其他网址:
from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls = ['http://www.example.com/sitemap.xml'] sitemap_rules = [ ('/product/', 'parse_product'), ('/category/', 'parse_category'), ] def parse_product(self, response): pass # ... scrape product ... def parse_category(self, response): pass # ... scrape category ...
关注robots.txt文件中定义的sitemaps,并且只跟踪其网址包含/sitemap_shop
以下内容的Sitemap :
from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls = ['http://www.example.com/robots.txt'] sitemap_rules = [ ('/shop/', 'parse_shop'), ] sitemap_follow = ['/sitemap_shops'] def parse_shop(self, response): pass # ... scrape shop here ...
将SitemapSpider与其他来源网址结合使用:
from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls = ['http://www.example.com/robots.txt'] sitemap_rules = [ ('/shop/', 'parse_shop'), ] other_urls = ['http://www.example.com/about'] def start_requests(self): requests = list(super(MySpider, self).start_requests()) requests += [scrapy.Request(x, self.parse_other) for x in self.other_urls] return requests def parse_shop(self, response): pass # ... scrape shop here ... def parse_other(self, response): pass # ... scrape other here ...
以上是Scrapy爬蟲入門教學四 Spider(爬蟲)的詳細內容。更多資訊請關注PHP中文網其他相關文章!