51Testing软件测试论坛

标题: scrapy框架的使用心得 [打印本页]

作者: 悠悠小仙仙    时间: 2019-6-11 11:46
标题: scrapy框架的使用心得
scrapy基础部分就不再做解析了,请移步:scrapy中文文档 https://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/overview.html
此次对scrapy应用是基于二次开发的,利用scrapy的框架的爬取大致流程,自己独立写模块,可以使开发流程更为简洁明了,降低了程序内部耦合,在实际应用过程中有一定的通用性, 而又不拘泥于scrapy原生的语法。

接下来分析一下我的scrapy,spider部分的结构

class lagouSpider(scrapy.Spider):
    handle_httpstatus_list = [500,503, 504, 400, 403, 404, 408]
    name = "lagou"
    allowed_domains = ["lagou.com"]
    start_urls = [(url_prefix.format(i) , i, 'company') for i in range(1, 180000)]

    def make_requests_from_url(self,url):
        request = scrapy.Request(url[0], callback=self.handle_parse,errback = self.handle_error)
        request.meta['index'] = url[1]
        request.meta['type'] = url[2]
        return request

要点:
1.当make_requests_from_url函数存在时,自动执行,将start_urls的每一个元素传入该函数,该元素类型可以为多种,本例中格式为列表, 目的是方便传入url内容的类型(如:公司,职位), 将其保存为meta
2.我们利用meta来传递一些用于标识的数据, 例如在拉勾网中,我们要爬取的公司的id,职位的类型和页码

def handle_parse(self, response):
    baseinfo = {'index':response.meta['index']}        #这里baseinfo用来保存到本地文件中,后续我们将往里添加各种信息
     maininfo = parse_company(response)                #parse_company是独立写的解析模块中的函数,源代码见GitHub
     if 'err' in maininfo:                             #解析中遇到错误时会有err信息,没有的话说明解析正确,继续执行
         info = {}
         info['index'] = baseinfo['index']
         info['type'] = response.meta['type']
         info['err'] = maininfo['err']
         #baseinfo['type'] = "NotFound"
         if maininfo['err']=='404 NotFound':
             self.f_404.write(json.dumps(info))
             self.f_404.write('\n')
         else:
             self.f_retry.write(json.dumps(info))
             self.f_retry.write('\n')
     else:
         info={}
         info['index']= baseinfo['index']
         info['type']='company'
         info['data']=maininfo

         self.f_success.write(json.dumps(info))               #将收集到的公司的信息保存为json格式,该格式便于阅读和分析
         self.f_success.write('\n')
         self.f_success.flush()                               #将内存里的数据写入硬盘,可以在爬取的过程中读取

         postCount = maininfo['dataInfo']['positionCount']    #postCount是统计该公司的职位数量
         if postCount!=0:                                     #如果职位数量不为0,分类查找岗位
             for i in ['技术','产品','运营','市场与销售','职能','金融','设计']:
                 url_post_prefix = "https://www.lagou.com/gongsi/searchPosition.json?companyId={}&positionFirstType={}&pageNo={}&pageSize=10"
                 url = url_post_prefix.format(baseinfo['index'], i, 1)    #生成新的url及相关信息,这里的url包含了岗位类型,url,和页数
                 request = scrapy.Request(url,cookies=cookie, callback=self.handle_parse_post, errback = self.handle_error)    #这里要爬取的类型为职位,回调函数设置为handle_parse_post
                 request.meta['type'] = 'post'              
                 request.meta['index'] = baseinfo['index']
                 request.meta['postType'] = i
                 request.meta['pageNo'] = 1
                 yield request              #这里利用yield,将request传给回调函数的同时函数继续运行
                 print 'company:{}正在加载,岗位类型为{},当前岗位第{}页'.format(baseinfo['index'], i, 1)




作者: Miss_love    时间: 2020-12-30 16:02
支持




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2