如何对淘宝商品爬虫信息进行采集或爬虫

&快来加入群【python爬虫交流群】(群号),发现精彩内容。
最近一直在看Scrapy 爬虫框架,并尝试使用Scrapy框架写一个可以实现网页信息采集的简单的小程序。尝试过程中遇到了很多小问题,希望大家多多指教。
本文主要介绍如何使用Scrapy结合PhantomJS采集天猫商品内容,文中自定义了一个DOWNLOADER_MIDDLEWARES,用来采集需要加载js的动态网页内容。看了很多介绍DOWNLOADER_MIDDLEWARES资料,总结来说就是使用简单,但会阻塞框架,所以性能方面不佳。一些资料中提到了自定义DOWNLOADER_HANDLER或使用scrapyjs可以解决阻塞框架的问题,有兴趣的小伙伴可以去研究一下,这里就不多说了。
2,具体实现
2.1,环境需求
需要执行以下步骤,准备Python开发和运行环境:
Python&下载安装并部署好环境变量 (本文使用Python版本为3.5.1)
lxml&下载对应版本的.whl文件,然后命令行界面执行 &pip install .whl文件路径&
Scrapy&命令行界面执行 &pip install Scrapy&,详细请参考
selenium&命令行界面执行 &pip install selenium&
PhantomJS &下载
上述步骤展示了两种安装:1,安装下载到本地的wheel包;2,用Python安装管理器执行远程下载和安装。注:包的版本需要和python版本配套
2.2,开发和测试过程
首先找到需要采集的网页,这里简单找了一个天猫商品,网址,页面如下:
然后开始编写代码,以下代码默认都是在命令行界面执行
1),创建scrapy爬虫项目tmSpider
E:\python-3.5.1>scrapy startproject tmSpider
2),修改settings.py配置
更改ROBOTSTXT_OBEY的值为False;
关闭scrapy默认的下载器中间件;
加入自定义DOWNLOADER_MIDDLEWARES。
配置如下:
DOWNLOADER_MIDDLEWARES = {
&&&&&span class="hljs-string"&'tmSpider.middlewares.middleware.CustomMiddlewares'&/span&: &span class="hljs-number"&543&/span&,
&&&&&span class="hljs-string"&'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware'&/span&: &span class="hljs-keyword"&None&/span&
3),在项目目录下创建middlewares文件夹,然后在文件夹下创建middleware.py文件,代码如下:
&span class="hljs-comment"&# -*- coding: utf-8 -*-&/span&
&span class="hljs-keyword"&from&/span& scrapy.exceptions &span class="hljs-keyword"&import&/span& IgnoreRequest
&span class="hljs-keyword"&from&/span& scrapy.http &span class="hljs-keyword"&import&/span& HtmlResponse, Response
&span class="hljs-keyword"&import&/span& tmSpider.middlewares.downloader &span class="hljs-keyword"&as&/span& downloader
&span class="hljs-class"&&span class="hljs-keyword"&class&/span& &span class="hljs-title"&CustomMiddlewares&/span&&span class="hljs-params"&(object)&/span&:&/span&
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&process_request&/span&&span class="hljs-params"&(self, request, spider)&/span&:&/span&
&&&&&&&&url = str(request.url)
&&&&&&&&dl = downloader.CustomDownloader()
&&&&&&&&content = dl.VisitPersonPage(url)
&&&&&&&&&span class="hljs-keyword"&return&/span& HtmlResponse(url, status = &span class="hljs-number"&200&/span&, body = content)
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&process_response&/span&&span class="hljs-params"&(self, request, response, spider)&/span&:&/span&
&&&&&&&&&span class="hljs-keyword"&if&/span& len(response.body) == &span class="hljs-number"&100&/span&:
&&&&&&&&&&&&&span class="hljs-keyword"&return&/span& IgnoreRequest(&span class="hljs-string"&"body length == 100"&/span&)
&&&&&&&&&span class="hljs-keyword"&else&/span&:
&&&&&&&&&&&&&span class="hljs-keyword"&return&/span& response
4),使用selenium和PhantomJS写一个网页内容下载器,同样在上一步创建好的middlewares文件夹中创建downloader.py文件,代码如下:
&span class="hljs-comment"&# -*- coding: utf-8 -*-&/span&
&span class="hljs-keyword"&import&/span& time
&span class="hljs-keyword"&from&/span& scrapy.exceptions &span class="hljs-keyword"&import&/span& IgnoreRequest
&span class="hljs-keyword"&from&/span& scrapy.http &span class="hljs-keyword"&import&/span& HtmlResponse, Response
&span class="hljs-keyword"&from&/span& selenium &span class="hljs-keyword"&import&/span& webdriver
&span class="hljs-keyword"&import&/span& selenium.webdriver.support.ui &span class="hljs-keyword"&as&/span& ui
&span class="hljs-class"&&span class="hljs-keyword"&class&/span& &span class="hljs-title"&CustomDownloader&/span&&span class="hljs-params"&(object)&/span&:&/span&
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&__init__&/span&&span class="hljs-params"&(self)&/span&:&/span&
&&&&&&&&&span class="hljs-comment"&# use any browser you wish&/span&
&&&&&&&&cap = webdriver.DesiredCapabilities.PHANTOMJS
&&&&&&&&cap[&span class="hljs-string"&"phantomjs.page.settings.resourceTimeout"&/span&] = &span class="hljs-number"&1000&/span&
&&&&&&&&cap[&span class="hljs-string"&"phantomjs.page.settings.loadImages"&/span&] = &span class="hljs-keyword"&True&/span&
&&&&&&&&cap[&span class="hljs-string"&"phantomjs.page.settings.disk-cache"&/span&] = &span class="hljs-keyword"&True&/span&
&&&&&&&&cap[&span class="hljs-string"&"phantomjs.page.customHeaders.Cookie"&/span&] = &span class="hljs-string"&'SINAGLOBAL=6.953297; '&/span&
&&&&&&&&self.driver = webdriver.PhantomJS(executable_path=&span class="hljs-string"&'F:/phantomjs/bin/phantomjs.exe'&/span&, desired_capabilities=cap)
&&&&&&&&wait = ui.WebDriverWait(self.driver,&span class="hljs-number"&10&/span&)
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&VisitPersonPage&/span&&span class="hljs-params"&(self, url)&/span&:&/span&
&&&&&&&&print(&span class="hljs-string"&'正在加载网站.....'&/span&)
&&&&&&&&self.driver.get(url)
&&&&&&&&time.sleep(&span class="hljs-number"&1&/span&)
&&&&&&&&&span class="hljs-comment"&# 翻到底,详情加载&/span&
&&&&&&&&js=&span class="hljs-string"&"var q=document.documentElement.scrollTop=10000"&/span&
&&&&&&&&self.driver.execute_script(js)
&&&&&&&&time.sleep(&span class="hljs-number"&5&/span&)
&&&&&&&&content = self.driver.page_source.encode(&span class="hljs-string"&'gbk'&/span&, &span class="hljs-string"&'ignore'&/span&)
&&&&&&&&print(&span class="hljs-string"&'网页加载完毕.....'&/span&)
&&&&&&&&&span class="hljs-keyword"&return&/span& content
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&__del__&/span&&span class="hljs-params"&(self)&/span&:&/span&
&&&&&&&&self.driver.quit()
5) 创建爬虫模块
在项目目录E:python-3.5.1tmSpider,执行如下代码:
&span class="hljs-attribute"&E&/span&:\python-&span class="hljs-number"&3.5&/span&&span class="hljs-number"&.1&/span&\tmSpider>scrapy genspider tmall &span class="hljs-string"&''&/span&
执行后,项目目录E:python-3.5.1tmSpidertmSpiderspiders下会自动生成tmall.py程序文件。该程序中parse函数处理scrapy下载器返回的网页内容,采集网页信息的方法可以是:
使用xpath或正则方式从response.body中采集所需字段,
通过gooseeker api获取的内容提取器实现一站转换所有字段,而且不用手工编写转换用的xpath(如何获取内容提取器请参考),代码如下:
&span class="hljs-comment"&# -*- coding: utf-8 -*-&/span&
&span class="hljs-keyword"&import&/span& time
&span class="hljs-keyword"&import&/span& scrapy
&span class="hljs-keyword"&import&/span& tmSpider.gooseeker.gsextractor &span class="hljs-keyword"&as&/span& gsextractor
&span class="hljs-class"&&span class="hljs-keyword"&class&/span& &span class="hljs-title"&TmallSpider&/span&&span class="hljs-params"&(scrapy.Spider)&/span&:&/span&
&&&&name = &span class="hljs-string"&"tmall"&/span&
&&&&allowed_domains = [&span class="hljs-string"&""&/span&]
&&&&start_urls = (
&&&&&&&&&span class="hljs-string"&'/item/.htm'&/span&,
&&&&&span class="hljs-comment"&# 获得当前时间戳&/span&
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&getTime&/span&&span class="hljs-params"&(self)&/span&:&/span&
&&&&&&&&current_time = str(time.time())
&&&&&&&&m = current_time.find(&span class="hljs-string"&'.'&/span&)
&&&&&&&&current_time = current_time[&span class="hljs-number"&0&/span&:m]
&&&&&&&&&span class="hljs-keyword"&return&/span& current_time
&&&&&span class="hljs-function"&&span class="hljs-keyword"&def&/span& &span class="hljs-title"&parse&/span&&span class="hljs-params"&(self, response)&/span&:&/span&
&&&&&&&&html = response.body
&&&&&&&&print(&span class="hljs-string"&"----------------------------------------------------------------------------"&/span&)
&&&&&&&&extra=gsextractor.GsExtractor()
&&&&&&&&extra.setXsltFromAPI(&span class="hljs-string"&"0ae7b8baa"&/span&, &span class="hljs-string"&"淘宝天猫_商品详情30474"&/span&,&span class="hljs-string"&"tmall"&/span&,&span class="hljs-string"&"list"&/span&)
&&&&&&&&result = extra.extract(html)
&&&&&&&&print(str(result).encode(&span class="hljs-string"&'gbk'&/span&, &span class="hljs-string"&'ignore'&/span&).decode(&span class="hljs-string"&'gbk'&/span&))
&&&&&&&&&span class="hljs-comment"&#file_name = 'F:/temp/淘宝天猫_商品详情30474_' + self.getTime() + '.xml'&/span&
&&&&&&&&&span class="hljs-comment"&#open(file_name,"wb").write(result)&/span&
6),启动爬虫
在E:python-3.5.1tmSpider项目目录下执行命令
E:\python-3.5.1\simpleSpider>scrapy crawl tmall
提一下,上述命令只能一次启动一个爬虫,如果想同时启动多个呢?那就需要自定义一个爬虫启动模块了,在spiders下创建模块文件runcrawl.py,代码如下
&span class="hljs-comment"&# -*- coding: utf-8 -*-&/span&
&span class="hljs-keyword"&import&/span& scrapy
&span class="hljs-keyword"&from&/span& twisted.internet &span class="hljs-keyword"&import&/span& reactor
&span class="hljs-keyword"&from&/span& scrapy.crawler &span class="hljs-keyword"&import&/span& CrawlerRunner
&span class="hljs-keyword"&from&/span& tmall &span class="hljs-keyword"&import&/span& TmallSpider
spider = TmallSpider(domain=&span class="hljs-string"&''&/span&)
runner = CrawlerRunner()
runner.crawl(spider)
d = runner.join()
d.addBoth(&span class="hljs-keyword"&lambda&/span& _: reactor.stop())
reactor.run()
执行runcrawl.py文件,输出结果:
以自定义DOWNLOADER_MIDDLEWARES调用PhantomJs的方式实现爬虫后,在阻塞框架的问题上纠结了很长的时间,一直在想解决的方式。后续会研究一下scrapyjs,splash等其他调用浏览器的方式看是否能有效的解决这个问题。
4,相关文档
5,集搜客GooSeeker开源代码下载源
6,文档修改历史
原文链接:/a/6893
注:转载文章均来自于公开网络,仅供学习使用,不会用于任何商业用途,如果侵犯到原作者的权益,请您与我们联系删除或者授权事宜,联系邮箱:contact@dataunion.org。转载数盟网站文章请注明原文章作者,否则产生的任何版权纠纷与数盟无关。
阅读(...) 评论()博客访问: 1518663
博文数量: 289
博客积分: 2907
博客等级: 中校
技术积分: 1437
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: Python/Ruby
想从淘宝上抓点数据,做分析,看了下别人写的,不难,遂试着写了个(APK爬虫-门钥匙,虾米爬虫-门钥匙)
对代码进行了重构,是逻辑跟清晰,抓取网页都要调用aragog(url, anaylze_func)函数,其中url为网址,analyze_func为解析页面方法
放弃MySQL数据库,使用csv作为存储
加入错误日志,通过try/except提高程序的健壮性
启动程序时加入日志和数据路径变量,以及关键词
eg:python main.py /home/user/aragog 核桃 木耳 香菇
# -*- coding: utf-8 -*-
__author__ = 'seven'
import os, urllib2, datetime
from sys import argv
from urlparse import urlparse
from BeautifulSoup import BeautifulSoup
timestamp = datetime.datetime.now().strftime('%Y-%m-%d')
path = os.getcwd()
keywords = []
keyword = ''
#接收存储路径和关键字
if len(argv) & 2:
&&&&path = argv[1]
&&&&keywords = argv[2:]
def aragog(url, analyze_func):
&&&&爬虫入口
&&&&print url
&&&&page = urllib2.urlopen(url, timeout=20)
&&&&if page.code != 200:
&&&&&&&&insert_log('request,{0},{1}'.format(page.code, url))
&&&&&&&&return
&&&&&&&&page = page.read().decode('gbk').encode('utf-8')
&&&&except Exception:
&&&&&&&&insert_log('unicode,转码错误,' + url)
&&&&&&&&return
&&&&&&&&soup = BeautifulSoup(page)
&&&&&&&&#给BeautifulSoup添加url属性,存放当前页面的URL
&&&&&&&&soup.url = url
&&&&&&&&return analyze_func(soup)
def insert_log(record):
&&&&打印错误日志
&&&&with open(path + '/log.csv', 'a') as log:
&&&&&&&&log.write('{time},{record},\r\n'.format(
&&&&&&&&&&&&time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
&&&&&&&&&&&&record = record
&&&&&&&&))
def get_pages_total(soup):
&&&&获得搜索结果的页数
&&&&&&&&return int(soup.find('span', {'class' : 'page-info'}).string.split('/')[1])
&&&&except Exception:
&&&&&&&&insert_log('analyze,获取页数失败,' + soup.url)
&&&&&&&&return 0
def analyze_search(soup):
&&&&搜索结果页面解析
&&&&for item in soup.find('div', {'id' : 'list-content'}).findAll('li', {'class' : 'list-item'}):
&&&&&&&&try:
&&&&&&&&&&&&record = to_utf8(format_item_url(item.h3.a['href'])) + ','
&&&&&&&&&&&&record += to_utf8(item.h3.a['title']) + ','
&&&&&&&&&&&&record += to_utf8(item.find('li', {'class' : 'price'}).em.string) + ','
&&&&&&&&&&&&record += to_utf8(item.find('li', {'class' : 'seller'}).a.string) + ','
&&&&&&&&&&&&record += to_utf8(item.find('span', {'class' : 'loc'}).string) + ','
&&&&&&&&except Exception:
&&&&&&&&&&&&insert_log('analyze,页面解析错误,' + soup.url)
&&&&&&&&else:
&&&&&&&&&&&&with open('{path}/{time}_{keyword}.csv'.format(
&&&&&&&&&&&&&&&&path = path,
&&&&&&&&&&&&&&&&time = timestamp,
&&&&&&&&&&&&&&&&keyword = keyword
&&&&&&&&&&&&), 'a') as data:
&&&&&&&&&&&&&&&&data.write(record + '\r\n')
def analyze_item(soup):
&&&&if 'chaoshi' in soup.url:
&&&&&&&&return analyze_item_chaoshi(soup)
&&&&elif 'tmall' in soup.url:
&&&&&&&&return analyze_item_tmall(soup)
&&&&&&&&return analyze_item_taobao(soup)
def analyze_item_tmall(soup):
&&&&天猫页面解析
&&&&&&&&record = to_utf8(urlparse(soup.find('div', {'class' : 'shop-intro'})\
&&&&&&&&&&&&.find('a', {'class' : 'enter'})['href']).hostname) + ','
&&&&&&&&record += to_utf8(soup.find('li', {'class' : 'tb-clearfix'}).text) + ','
&&&&&&&&record += to_utf8(soup.find('em', {'class' : 'J_MonSalesNum'}).string) + ','
&&&&except Exception:
&&&&&&&&insert_log('analyze,页面解析错误,' + soup.url)
&&&&&&&&return ''
&&&&&&&&return record
def analyze_item_taobao(soup):
&&&&淘宝页面解析
&&&&if len(soup.text) & 200:
&&&&&&&&try:
&&&&&&&&&&&&record = to_utf8(urlparse(soup.find('a', {'class' : 'tb-enter-shop'})[
&&&&&&&&&&&&&&&&&&&&&&&&&&&'href']).hostname) + ','
&&&&&&&&&&&&record += to_utf8(soup.find('li', {'class' : 'tb-clearfix'}).text) + ','
&&&&&&&&&&&&record += to_utf8(soup.find('em', {'class' : 'J_TDealCount'})
&&&&&&&&&&&&&&&&.string) + ','
&&&&&&&&except Exception:
&&&&&&&&&&&&insert_log('analyze,页面解析错误,' + soup.url)
&&&&&&&&&&&&return ''
&&&&&&&&else:
&&&&&&&&&&&&return record
&&&&&&&&return aragog(soup.url.replace('://item', '://meal'), analyze_item_taobao)
def analyze_item_chaoshi(soup):
&&&&天猫超市页面解析
&&&&&&&&record = ','
&&&&&&&&record += to_utf8(soup.find('ul', {'class' : 'tb-meta'}).findAll(
&&&&&&&&&&&&'li')[3].text) + ','
&&&&&&&&record += to_utf8(soup.find('li', {'class' : 'tb-sold-out'}).em
&&&&&&&&&&&&.string) + ','
&&&&except Exception:
&&&&&&&&insert_log('analyze,页面解析错误,' + soup.url)
&&&&&&&&return ''
&&&&&&&&return record
def query_2_dict(query):
&&&&将URL的query由字符串转为字典
&&&&return eval('{\''+query.replace('=', '\':\'').replace('&', '\',\'')+'\'}')
def format_item_url(url):
&&&&去掉产品页面URL中query中无关的数据
&&&&淘宝产品页面有五种『淘宝,天猫,推广产品,天猫超市,淘宝生态农业』
&&&&其中淘宝生态农业页面有淘宝产品页面通过js指向过去,这里暂不考虑
&&&&淘宝和天猫规则一样
&&&&推广产品里面url包含‘,去掉即可
&&&&天猫超市直接返回
&&&&if '' in url:
&&&&&&&&url = urlparse(url).query[4:]
&&&&&&&&url = format_item_url(url)
&&&&elif not 'chaoshi' in url:
&&&&&&&&try:
&&&&&&&&&&&&parse = urlparse(url)
&&&&&&&&&&&&url = "http://{0}{1}?id={2}".format(parse.netloc,
&&&&&&&&&&&&&&&&parse.path, query_2_dict(parse.query)['id'])
&&&&&&&&except Exception:
&&&&&&&&&&&&insert_log('url,'+url)
&&&&return url
def to_utf8(string):
&&&&字符由unicode转为utf-8
&&&&if isinstance(string, unicode):
&&&&&&&&string = string.encode('utf-8')
&&&&if string == None:
&&&&&&&&string = ''
&&&&return string
if __name__ == '__main__':
&&&&#获取产品列表
&&&&for keyword in keywords:
&&&&&&&&keyword = keyword
&&&&&&&&search_url = '/search?q=' + urllib2.quote(keyword)
&&&&&&&&for i in range(aragog(search_url, get_pages_total)):
&&&&&&&&&&&&aragog('{0}&s={1}'.format(search_url, i*40), analyze_search)
&&&&#获取产品详情
&&&&for keyword in ['核桃']:
&&&&&&&&lines = []
&&&&&&&&with open('{path}/{time}_{keyword}.csv'.format(
&&&&&&&&&&&&path = path,
&&&&&&&&&&&&time = timestamp,
&&&&&&&&&&&&keyword = keyword
&&&&&&&&), 'r') as data:
&&&&&&&&&&&&for line in data.readlines():
&&&&&&&&&&&&&&&&new_line = aragog(line.split(',')[0], analyze_item)
&&&&&&&&&&&&&&&&lines.append(line.replace('\n', ',' + new_line + '\r\n'))
&&&&&&&&with open('{path}/{time}_{keyword}.csv'.format(
&&&&&&&&&&&&path = path,
&&&&&&&&&&&&time = timestamp,
&&&&&&&&&&&&keyword = keyword
&&&&&&&&), 'w') as data:
&&&&&&&&&&&&data.writelines(lines)
用了30个番茄.解析页面,解决字符编码,重构是耗时最多三项.
解析页面使用的是BeautifulSoup,是看了上面两篇日志选的,第一次写耗时多不为过.
字符编码的问题一直是我头疼的问题,这次花点时间,深入了解下,以后可以不用头疼字符编码问题.
重构耗时,我认为是性格导致,当功能还没实现,就构思着怎么重构,导致进度不前.
整体来说用python写爬虫还是很简单的.
上面是运行爬虫时CPU,内存和网络使用情况,CPU处理能力还有极大富余,网络理由率不高,所以性能还可以提高.
在解析页面的过程中,不够灵活,弱爆了,而且数据有误会导致程序终止.
综和上面的问题,将对爬虫进行一下改进
提高程序的健壮性,加入log,提高页面解析灵活性.
继续重构代码,尽可能搞的提高性能,使用多线程.
阅读(14202) | 评论(4) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
这里有现成写好的淘宝商品信息及评论采集爬虫,可以直接使用,有兴趣的童鞋可以试下/index.php?r=market/configDetail&pid=119
楼主将的很不错&不过代码太长了&建议可以看看这个系列的博客&专门讲解如何写电商网站爬虫的&写的爬虫很简洁:http://blog.csdn.net/youmumzcs/article/details/
&QQ&有事情找你
请登录后评论。1122人阅读
淘宝采集研究
淘宝网api现在限制外网接入,而且也限制调用次数,所以想抓取到商品的价格信息,只有通过自己直接爬取淘宝网商品页面,解析出商品的价格和促销价格了。
下面介绍爬取和解析淘宝商品价格的方法:
直接根据商品的链接抓取到商品页面信息,分析商品页面信息可以发现里面直接就有商品的价格信息,但是没有促销价格。下面是含有价格信息的html代码片段
&strongid=&J_StrPrice& &&emclass=&tb-rmb&&¥&/em&&emclass=&tb-rmb-num&&100.00&/em&&/strong&&/div&
商品价格信息直接从html中提取就可以了,在此不再详细写如何提取,不会提取的 可以在文章结尾下载php源码分析下就行。
下面重点来说下如何得到商品促销价格,用firebug 分析页面加载信息发现,淘宝商品促销价格是通过ajax的方式动态加载的。所以要获取到商品促销价格,就必须知道,ajax请求的url。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1125次
排名:千里之外}

我要回帖

更多关于 爬虫获取淘宝商品数据 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信