python - pyspider 里 pyquery的 map方法 映射的返回值 无效导致单页能调试通,整体采集不到数据?
PHP中文网
PHP中文网 2017-04-17 16:47:55
0
1
905

昨天用 pyspider 采集 汽车之家网 的 汽车详情页数据,因为他一条记录是table 中的某一列,所以需要用到遍历td,索引取当前列。找了半天 没实现jq的 .index() 方法。只找到map 方法。

就用map 写了属性的拼装。

代码如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2015-12-27 14:58:45
# Project: goods2

from pyspider.libs.base_handler import *


class Handler(BaseHandler):
    crawl_config = {
    }

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('http://www.autohome.com.cn/car/?pvareaid=101452', callback=self.index_page)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        for each in response.doc('.find-letter-list li a').items():
            self.crawl('http://www.autohome.com.cn/grade/carhtml/'+each.text()+'.html', callback=self.detail_page)

    @config(priority=2)
    def detail_page(self, response):
        for each in response.doc('.rank-list-ul li[id] h4 a').items():
            self.crawl(each.attr.href, callback=self.jump_page, fetch_type='js')

    @config(priority=2)
    def jump_page(self, response):
        self.crawl(response.doc('#navTop a:contains("'+u'参数配置'+'")').attr.href, callback=self.deep_page, fetch_type='js')

    def deep_page(self, response):

        return response.doc('.tbset tr:eq(0) td').filter(lambda i: response.doc(this).find('.btn_delbar').length).map(lambda i, e: {
            'goods_name': response.doc(e).find('.carbox p a').text(),
            'brand_name': response.doc('#tr_0 td').eq(i).text(),
            'c_name': response.doc('.subnav-title-name a').text().split('-')[0],
            's_name': response.doc('.subnav-title-name a').text().split('-')[1],
            'goods_sn': '',
            'goods_name_style':'+',
            'click_count': 0,
            'provider_name': '',
            'goods_number': 100,
            'goods_weight': 0,
            'market_price': response.doc('#tr_2000 td').eq(i).text(), #待处理成float 元为单位
            'shop_price': response.doc('#tr_2001 td').eq(i).find('.pircecont').text(), #待处理成float 元为单位
            'warn_number': 1,
            'goods_desc': u'0.0升 '+ response.doc('#tr_30 td').eq(i).text()+' '+ response.doc('#tr_38 td').eq(i).text()+u'马力 '+ "\n" + response.doc('#tr_53 td').eq(i).text() + ' '+ response.doc('#tr_3 td').eq(i).text(),
            'is_real':1,
            'is_alone_sale':1, #1-普通 0-赠品
            'sort_order':100,
            'goods_type':1,
            'attributes':
            [
                {
                    'attr_name': each('th').text(),
                    'attr_value': each('td').eq(i).find('a').attr.title if (each.attr.id == 'tr_2003' or each.attr.id == 'tr_2004')
                           else each('td').eq(i).text()
                    ,
                } for each in response.doc('tr[id^="tr_"]').items()
            ]
        })

开始不知道什么原因,后来群里 自由人帮我调试出问题, 返回值不对,小弟python自学的,求作者指点。我去看看群里教程视频了。先把返回 改为table 字符串没解决就用php去解析了。

PHP中文网
PHP中文网

认证0级讲师

모든 응답(1)
小葫芦

나중에 발견된 이유:

  • 한 페이지의 여러 데이터가 send_message로 처리됩니다.

  • 설치된 pyspider pip가 최신 버전이 아닙니다. github로 이동하여 다운로드하세요.

  • pyquery response.doc의 반환된 객체 맵은 주의해서 사용해야 합니다. 열거할 때 i, e에 사용하세요.

  • 마지막으로 수정된 스크립트:

    pyspider.libs.base_handler에서 가져오기 *
    
    
    클래스 핸들러(베이스 핸들러):
        크롤링_구성 = {
        }
    
        @every(분=24 * 60)
        def on_start(self):
            self.crawl('http://www.autohome.com.cn/car/?pvareaid=101452', callback=self.index_page)
    
        @config(나이=10 * 24 * 60 * 60)
        def index_page(self, response):
            response.doc('.find-letter-list li a').items()의 각각에 대해:
                self.crawl('http://www.autohome.com.cn/grade/carhtml/'+each.text()+'.html', callback=self.detail_page)
    
        @config(우선순위=2)
        def Detail_page(자기, 응답):
            response.doc('.rank-list-ul li[id] h4 a').filter(lambda i: response.doc(this).not_('.greylink').length).items()의 각각에 대해:
                self.crawl(each.attr.href, callback=self.jump_page, fetch_type='js')
    
        @config(우선순위=2)
        def jump_page(자체, 응답):
            self.crawl(response.doc('#navTop a:contains("'+u'매개변수 구성'+'")').attr.href, callback=self.deep_page, fetch_type='js')
    
        def deep_page(self, response):
            tds = response.doc('.tbset tr:eq(0) td').filter(lambda i: response.doc(this).find('.btn_delbar').length)
            i, e의 경우 enumerate(tds.items()):
                self.send_message(self.project_name, {
                    'url': 응답.url,
                    '상품_이름': response.doc(e).find('.carbox p a').text(),
                    '브랜드_이름': response.doc('#tr_0 td').eq(i).text(),
                    'c_name': response.doc('.subnav-title-name a').text().split('-')[0],
                    's_name': response.doc('.subnav-title-name a').text().split('-')[1],
                    'goods_sn': '',
                    '상품_이름_스타일':'+',
                    '클릭 횟수': 0,
                    '공급자_이름': '',
                    '상품_번호': 100,
                    '상품_중량': 0,
                    'market_price': response.doc('#tr_2000 td').eq(i).text(), #단위는 부동 위안화로 처리됩니다.
                    'shop_price': response.doc('#tr_2001 td').eq(i).find('.pircecont').text(), #부동 위안화로 처리됨
                    '경고_번호': 1,
                    'goods_desc': u'0.0liter'+ response.doc('#tr_30 td').eq(i).text()+' '+ response.doc('#tr_38 td').eq(i).text ()+u'마력'+ "\n" + response.doc('#tr_53 td').eq(i).text() + ' '+ response.doc('#tr_3 td').eq(i).text(),
                    'is_real':1,
                    'is_alone_sale':1, #1-일반 0-선물
                    '정렬_순서':100,
                    '상품_유형':1,
                    '속성':
                    [
                        {
                            'attr_name': 각('th').text(),
                            'attr_value': Each('td').eq(i).find('a').attr.title if (each.attr.id == 'tr_2003' 또는 Each.attr.id == 'tr_2004')
                                   else 각각('td').eq(i).text()
                            ,
                        } response.doc('tr[id^="tr_"]').items() 각각에 대해
                    ]
               }, url="%s#%s" % (response.url, i))
    
        def on_message(자기, 프로젝트, 메시지):
            메시지 반환

    pyspider 그룹 멤버 Freeman에게 감사드립니다(397340469)

    최신 다운로드
    더>
    웹 효과
    웹사이트 소스 코드
    웹사이트 자료
    프론트엔드 템플릿