Scrapy_CrawlSpider

CrawlSpider:Spider的子类

1.Spider的用法:

name
定义spider名字的字符串(string)。

allow_domains
允许爬取的域名,是可选配置,不在此域名范围的链接,不会被跟进爬取。

start_urls
URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面
的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。


start_requests()
此方法用于生成初始请求,它必须必须返回一个可迭代对象。此方法会默认使用start_urls里面的URL来构建Request,
而且Request是以GET方式进行请求。如果我们想在启动时,想以POST的请求方式访问某个网站,可以直接重写这个方法。


parse()
当response没有指定回调函数时,该方法是Scrapy处理下载的response的默认方法。
parse 负责处理response并返回处理的数据以及(/或)跟进的URL。 Spider 对其他的Request的回调函数也有相同的要求。
该方法及其他的Request回调函数必须返回一个包含 Request、dict 或 Item 的可迭代的对象。


close()
当spider关闭时,该函数被调用。有一个参数reason,表示当前参数中断的原因。

2.CrawlSpider源码

class CrawlSpider(Spider):
 
    rules = ()
 
    def __init__(self, *a, **kw):
        super(CrawlSpider, self).__init__(*a, **kw)
        self._compile_rules()
 
    #1、首先调用parse()方法来处理start_urls中返回的response对象。
    #2、parse()将这些response对象传递给了_parse_response()函数处理,并设置回调函数为parse_start_url()。
    #3、设置了跟进标志位True,即follow=True。
    #4、返回response。
    def parse(self, response):
        return self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True)
 
    #处理start_url中返回的response,需要重写。
    def parse_start_url(self, response):
        return []
 
    def process_results(self, response, results):
        return results
 
    def _build_request(self, rule, link):
         #构造Request对象,并将Rule规则中定义的回调函数作为这个Request对象的回调函数。这个‘_build_request’函数在下面调用。
        r = Request(url=link.url, callback=self._response_downloaded)
        r.meta.update(rule=rule, link_text=link.text)
        return r
 
    #从response中抽取符合任一用户定义'规则'的链接,并构造成Resquest对象返回。
    def _requests_to_follow(self, response):
        if not isinstance(response, HtmlResponse):
            return
        seen = set()
        #抽取所有链接,只要通过任意一个'规则',即表示合法。 
        for n, rule in enumerate(self._rules):
            links = [lnk for lnk in rule.link_extractor.extract_links(response)
                     if lnk not in seen]
            if links and rule.process_links:
                links = rule.process_links(links)
            #将链接加入seen集合,为每个链接生成Request对象,并设置回调函数为_repsonse_downloaded()。
            for link in links:
                seen.add(link)
                #构造Request对象,并将Rule规则中定义的回调函数作为这个Request对象的回调函数。这个‘_build_request’函数在上面定义。
                r = self._build_request(n, link)
                #对每个Request调用process_request()函数。该函数默认为indentify,即不做任何处理,直接返回该Request。
                yield rule.process_request(r)
 
    #处理通过rule提取出的连接,并返回item以及request。
    def _response_downloaded(self, response):
        rule = self._rules[response.meta['rule']]
        return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow)
 
    #解析response对象,使用callback解析处理他,并返回request或Item对象。
    def _parse_response(self, response, callback, cb_kwargs, follow=True):
        #1、首先判断是否设置了回调函数。(该回调函数可能是rule中的解析函数,也可能是 parse_start_url函数)  
        #2、如果设置了回调函数(parse_start_url()),那么首先用parse_start_url()处理response对象,  
        #3、然后再交给process_results处理。返回cb_res的一个列表。  
        if callback:
            cb_res = callback(response, **cb_kwargs) or ()
            cb_res = self.process_results(response, cb_res)
            for requests_or_item in iterate_spider_output(cb_res):
                yield requests_or_item
 
        #如果需要跟进,那么使用定义的Rule规则提取并返回这些Request对象。
        if follow and self._follow_links:
            #返回每个Request对象。
            for request_or_item in self._requests_to_follow(response):
                yield request_or_item
 
    def _compile_rules(self):
        def get_method(method):
            if callable(method):
                return method
            elif isinstance(method, six.string_types):
                return getattr(self, method, None)
 
        self._rules = [copy.copy(r) for r in self.rules]
        for rule in self._rules:
            rule.callback = get_method(rule.callback)
            rule.process_links = get_method(rule.process_links)
            rule.process_request = get_method(rule.process_request)
 
    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(CrawlSpider, cls).from_crawler(crawler, *args, **kwargs)
        spider._follow_links = crawler.settings.getbool(
            'CRAWLSPIDER_FOLLOW_LINKS', True)
        return spider
 
    def set_crawler(self, crawler):
        super(CrawlSpider, self).set_crawler(crawler)
        self._follow_links = crawler.settings.getbool('CRAWLSPIDER_FOLLOW_LINKS', True)
 

举例1:首次get请求

from scrapy.spider import CrawlSpider
import scrapy
from bs4 import BeautifulSoup
from pss.pss.items import PssItem
class MySpider(CrawlSpider):
    name = 'myspider'
    start_urls=['http://lol.qq.com/web201310/info-heros.shtml#Navi']
    def parse(self, response):
        print(response.body.decode('utf-8'))
        soup = BeautifulSoup(response.body.decode('utf-8'), 'html.parser')
        tags = soup.select('#jSearchHeroDiv > li > a > img')
        for tag in tags:
            yield scrapy.Request(url=tag['src'],callback=self.download,meta={'name':tag['src'].split("/")[-1]})
    def download(self,response):
        item=PssItem()
        item['data']=response.body
        item['name']=response.meta['name']
        yield item

举例2:首次post请求

from scrapy.spider import CrawlSpider
import scrapy
import json
class LaGou(CrawlSpider):
    name = 'myspider'
    def start_requests(self):
        yield scrapy.FormRequest(
            url='https://www.lagou.com/jobs/positionAjax.json?city=%E5%B9%BF%E5%B7%9E&needAddtionalResult=false',
            #formdata中的key和value必须为字符串
            formdata={
                'first': 'true',#这里不能给bool类型的True
                'pn': '1',#这里不能给int类型的1
                'kd': 'python'
            },
            callback=self.parse
        )
    def parse(self, response):
        datas=json.loads(response.body.decode())['content']['positionResult']['result']
        for data in datas:
            print(data['companyFullName'] + str(data['positionId']))




猜你喜欢

转载自blog.csdn.net/rookie_is_me/article/details/85251419