您的位置:首页 > 编程语言 > Python开发

Python爬虫框架Scrapy 学习笔记 10.3 -------【实战】 抓取天猫某网店所有宝贝详情

2015-01-12 08:49 1456 查看
第三部分 替换默认下载器,使用selenium下载页面
对详情页稍加分析就可以得出:我们感兴趣的大部分信息都是由javascript动态生成的,因此需要先在浏览器中执行javascript代码,再从最终的页面上抓取信息(当然也有别的解决方案)。
scrapy 本身提供了 Middleware机制。利用Dowloader Middleware可以改变默认的request对象和reponse对象,甚至替换默认的下载器。(可以对比JavaEE中的Filter理解Middleware)

scrapy 架构图




由于middleware的配置比较复杂,在这里我们采用一个简单的方法:改用最简单的spider,在parse函数中用selenium下载详情页面。

改写CrawlSpider为默认Spider,在parse函数中获取详情页面的链接

# -*- coding: utf-8 -*-
import scrapy
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule

from tmall.items import TmallItem

class TmallSpider(CrawlSpider):
name = 'tmallSpider'
start_urls = ['http://shanhuijj.tmall.com/search.htm?spm=a1z10.3-b.w4011-3112923129.1.KjGkS2/']

rules = (
Rule(LinkExtractor(allow=r'http://detail.tmall.com/item.htm\?id=\d+&rn=\w+&abbucket=\d+',
restrict_xpaths="//div[@class='J_TItems']/div/dl/dd[@class='detail']"),
callback='parse_item', follow=False),
)

def parse(self, response):
linkExtractor = LinkExtractor(allow=r'http://detail.tmall.com/item.htm\?id=\d+&rn=\w+&abbucket=\d+',
restrict_xpaths="//div[@class='J_TItems']/div/dl/dd[@class='detail']")
linkList = linkExtractor.extract_links(response)
for link in linkList:
self.log("******************************************************")
self.log(link.url)


2. 用firefox打开详情页面链接,获取页面源文件,查看得到的源文件是不是执行过js的“源文件”
def parse(self, response):
linkExtractor = LinkExtractor(allow=r'http://detail.tmall.com/item.htm\?id=\d+&rn=\w+&abbucket=\d+',
restrict_xpaths="//div[@class='J_TItems']/div/dl/dd[@class='detail']")
linkList = linkExtractor.extract_links(response)
# open Firefox
browser = webdriver.Firefox()
file = open("C:\\pageSource.html", 'w'); flag = 0
for link in linkList:
browser.get(link.url)
pageSource = browser.page_source
if flag == 0:
file.write(pageSource)
file.close()
flag = 1

browser.close()
很不幸,试图写入文件时得到一个错误信息:

file.write(pageSource)
exceptions.UnicodeEncodeError: 'ascii' codec can't encode characters in position 8427-8443: ordinal not in range(128)
这是由于系统默认编码是ascii,python解释器试图将unicode编码的内容先转换成ascii编码再写入文件。
提前设置一下系统编码就可以解决这个问题。在文件头部加入:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
查看源文件发现,页面上信息还是不全,例如




可以很高兴地看到,累计评价的信息已经有了(在最初的源文件中是没有的),但是月销量的数字还没显示出来。原因可能是我们通过brower.page_source请求源码的时候,js还没执行完。我们等浏览器10秒钟再试一下
for link in linkList:
browser.get(link.url)
time.sleep(10)  # wait for 10 seconds
pageSource = browser.page_source
if flag == 0:
file.write(pageSource)
file.close()
flag = 1
此时再看得到的源文件,月销量的数据已经出现了



实际上除了月成交记录的详情信息,其它数据都已经出现在了源码里。
月成交记录的详情信息是鼠标触发的一个ajax请求,后面我们会用scrapy模拟ajax请求,这样可以直接从response中得到json格式交易记录详情。
到目前为止, spider的代码如下:
# -*- coding: utf-8 -*-

import sys reload(sys) sys.setdefaultencoding('utf-8')

import scrapy
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule
from selenium import webdriver
import time
from tmall.items import TmallItem

class TmallSpider(CrawlSpider):
name = 'tmallSpider'
start_urls = ['http://shanhuijj.tmall.com/search.htm?spm=a1z10.3-b.w4011-3112923129.1.KjGkS2/']

rules = (
Rule(LinkExtractor(allow=r'http://detail.tmall.com/item.htm\?id=\d+&rn=\w+&abbucket=\d+',
restrict_xpaths="//div[@class='J_TItems']/div/dl/dd[@class='detail']"),
callback='parse_item', follow=False),
)

def parse(self, response):
linkExtractor = LinkExtractor(allow=r'http://detail.tmall.com/item.htm\?id=\d+&rn=\w+&abbucket=\d+',
restrict_xpaths="//div[@class='J_TItems']/div/dl/dd[@class='detail']")
linkList = linkExtractor.extract_links(response)
# open Firefox
browser = webdriver.Firefox()
file = open("C:\\pageSource.html", 'wb'); flag = 0
for link in linkList:
browser.get(link.url)
time.sleep(10)
pageSource = browser.page_source
if flag == 0:
file.write(pageSource)
file.close()
flag = 1

browser.close()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐