首页 > 技术文章 > pyspider用PyQuery解析页面数据

shiluoliming 2018-01-29 20:39 原文

示例说明:

本示例主要是PyQuery解析返回的response页面数据。response.doc解析页面数据是pyspider的主要用法,应该熟练掌握基本使用方法。其他返回类型示例见后续文章。

pyspider爬取的内容通过回调的参数response返回,response有多种解析方式。
1、response.json用于解析json数据
2、response.doc返回的是PyQuery对象
3、response.etree返回的是lxml对象
4、response.text返回的是unicode文本
5、response.content返回的是字节码

使用方法:

PyQuery可以采用CSS选择器作为参数对网页进行解析。 关于PyQuery更多用法,可以参考PyQuery complete API。

PyQuery官方参考手册: https://pythonhosted.org/pyquery/

response.doc('.ml.mlt.mtw.cl > li').items()
response.doc('.pti > .pdbt > .authi > em > span').attr('title')

CSS选择器:更多详情请参考CSS Selector Reference

选择器示例示例说明
.class .intro Selects all elements with class=”intro”
#id #firstname Selects the element with id=”firstname”
element p Selects all <p> elements
element,element div, p Selects all <div> elements and all <p> elements
element element div p Selects all <p> elements inside <div> elements
element>element div > p Selects all <p> elements where the parent is a <div> element
[attribute] [target] Selects all elements with a target attribute
[attribute=value] [target=_blank] Selects all elements with target=”_blank”
[attribute^=value] a[href^=”https”] Selects every <a> element whose href attribute value begins with “https”
[attribute$=value] a[href$=”.pdf”] Selects every <a> element whose href attribute value ends with “.pdf”
[attribute*=value] a[href*=”w3schools”] Selects every <a> element whose href attribute value contains the substring “w3schools”
:checked input:checked Selects every checked <input> element

示例代码:

1、PyQuery基本语法应用

 

复制代码
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2016-10-09 15:16:04
# Project: douban_rent

from pyspider.libs.base_handler import *

groups = {'上海租房': 'https://www.douban.com/group/shanghaizufang/discussion?start=',
          '上海租房@长宁租房/徐汇/静安租房': 'https://www.douban.com/group/zufan/discussion?start=',
          '上海短租日租小组 ': 'https://www.douban.com/group/chuzu/discussion?start=',
          '上海短租': 'https://www.douban.com/group/275832/discussion?start=',
          }

class Handler(BaseHandler):
    crawl_config = {
    }

    @every(minutes=24 * 60)
    def on_start(self):
        for i in groups:
            url = groups[i] + '0'
            self.crawl(url, callback=self.index_page, validate_cert=False)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        for each in response.doc('.olt .title a').items():
            self.crawl(each.attr.href, callback=self.detail_page)

        #next page 
        for each in response.doc('.next a').items():
            self.crawl(each.attr.href, callback=self.index_page)

    @config(priority=2)
    def detail_page(self, response):
        count_not=0
        notlist=[]
        for i in response.doc('.bg-img-green a').items():
            if i.text() <> response.doc('.from a').text():
                count_not +=1 
                notlist.append(i.text())
        for i in notlist: print i

        return {
            "url": response.url,
            "title": response.doc('title').text(),
            "author": response.doc('.from a').text(),
            "time": response.doc('.color-green').text(),
            "content": response.doc('#link-report p').text(),
            "回应数": len([x.text() for x in response.doc('h4').items()])   ,
            # "最后回帖时间": [x for x in response.doc('.pubtime').items()][-1].text(),
            "非lz回帖数": count_not,
            "非lz回帖人数": len(set(notlist)),
            # "主演": [x.text() for x in response.doc('.actor a').items()],
        }
复制代码

 

2、PyQuery基本语法应用

复制代码
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2015-10-09 09:00:10
# Project: learn_pyspider_db

from pyspider.libs.base_handler import *
import re


class Handler(BaseHandler):
    crawl_config = {
    }

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('http://movie.douban.com/tag/', callback=self.index_page)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        for each in response.doc('.tagCol a').items():
            self.crawl(each.attr.href, callback=self.list_tag_page)

    @config(age=10 * 24 * 60 * 60)
    def list_tag_page(self, response):
        all = response.doc('.more-links')
        self.crawl(all.attr.href, callback=self.list_page)

    @config(age=10*24*60*60)
    def list_page(self, response):
        for each in response.doc('.title').items():
            self.crawl(each.attr.href, callback=self.detail_page)
        # craw the next page
        next_page = response.doc('.next > a')
        self.crawl(next_page.attr.href, callback=self.list_page)

    @config(priority=2)
    def detail_page(self, response):
        director = ''
        for item in response.doc('#info > span > .pl'):
            if item.text == u'导演':
                next_item = item.getnext()
                director = next_item.getchildren()[0].text
                break
        return {
            "url": response.url,
            "title": response.doc('title').text(),
            "director": director,
        }
复制代码

3、PyQuery复杂选择及翻页处理

复制代码
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2016-10-12 06:39:31
# Project: qx_zj_poi2

import re
from pyspider.libs.base_handler import *


class Handler(BaseHandler):
    crawl_config = {
    }

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('http://www.poi86.com/poi/amap/province/330000.html', callback=self.city_page)

    @config(age=24 * 60 * 60)
    def city_page(self, response):
        for each in response.doc('body > div:nth-child(2) > div > div.panel-body > ul > li > a').items():
            self.crawl(each.attr.href, callback=self.district_page)
    
    @config(age=24 * 60 * 60)
    def district_page(self, response):
        for each in response.doc('body > div:nth-child(2) > div > div.panel-body > ul > li > a').items():
            self.crawl(each.attr.href, callback=self.poi_idx_page)

    @config(age=24 * 60 * 60)
    def poi_idx_page(self, response):
        for each in response.doc('td > a').items():
            self.crawl(each.attr.href, callback=self.poi_dtl_page)
        # 翻页
        for each in response.doc('body > div:nth-child(2) > div > div.panel-body > div > ul > li:nth-child(13) > a').items():
            self.crawl(each.attr.href, callback=self.poi_idx_page)
            
    @config(priority=100)
    def poi_dtl_page(self, response):
        return {
            "url": response.url,
            "id": re.findall('\d+',response.url)[1],
            "name": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-heading > h1').text(),
            "province": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(1) > a').text(),
            "city": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(2) > a').text(),
            "district": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(3) > a').text(),
            "addr": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(4)').text(),
            "tel": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(5)').text(),
            "type": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(6)').text(),
            "dd_map": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(7)').text(),
            "hx_map": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(8)').text(),
            "bd_map": response.doc('body > div:nth-child(2) > div:nth-child(2) > div.panel-body > ul > li:nth-child(9)').text(),
        }

推荐阅读