(转载请注明出处)
哈喽,大家好~
前言:这次写这个小脚本的目的是为了给老师帮个小忙,爬取某一商品的信息,写完觉得这个程序似乎也可以用在更普遍的地方,所以就放出来给大家看看啦,然后因为是在很短时间写的,所以自然有很多不足之处,想着总之实现了功能再说吧,代码太丑大不了之后再重构吧(不存在的)
废话不多说,这个脚本首先是基于scrapy框架实现的,因为前面也说了是一整个项目的一部分嘛,但是我这里没有写出scrapy框架的其他部分,仅仅展示了spider文件的代码,如果你不了解scrapy,也许你并不能看懂程序的某些部分,但是没什么关系,因为spider是框架相对独立的一部分,所以你可以仅仅了解爬虫的部分就行了。至于为什么不写出scrapy的其他部分,是因为实际上也并没有对其他部分做什么修改,只是创建了一个初始框架,甚至你也看不到对数据库的输出(因为我根本没写),但是我们还是可以从命令行得到所需的数据的,至于具体的使用,就看自己的需求了(比如可以简单的把数据输出到excel表格),重点还是在于对数据的爬取和分析,接下来我们就来分析一下功能吧
1.指定任意一个或一类需要爬取的商品
2.爬取所有的商品链接
3.爬取所有商品链接的商品详细信息
4.我们这次爬取的信息包括:
(1)商品名称
(2)商品价格
(3)商品评论
以此来作为范例,当然同理也可以爬取其他信息
(1)最重要的第一步,是要获得商品的链接,但是要注意这里的链接,如果你只爬取一个确定的商品的话那么链接自然就是商品的界面链接,这样自然是很容易的,只需在浏览器找到你的商品然后复制其链接就可以了,但是我们也希望找到所有店家出售的此商品,或者甚至是某一类商品(比如与python有关的所有书籍),这样我们就不能只用一个链接,即url,来作为唯一的爬取对象。
所以我们的第一步其实是构建一个url的列表,以便之后的爬虫爬取。
首先我们进入淘宝的搜索界面,然后在搜索栏输入要搜索的商品,点击搜索
之后你自然会看到淘宝为你搜索出了所有有关的商品,这里我们要做的是复制当前网页的链接,这里以搜索python书籍为例
链接如下:
https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=python%E4%B9%A6%E7%B1%8D&suggest=history_1&_input_charset=utf-8&wq=p&suggest_query=p&source=suggest&sort=sale-desc&bcoffset=0&p4ppushleft=%2C44&s=0
大部分没什么用,我们主要关注中间的
q=python%E4%B9%A6%E7%B1%8D
你可以直接用 q=python书籍 替换它,这说明了q=的后面即是我们要输入的商品名称
然后我们再看链接的最后:
s=0
这个s代表的就是商品的当前页,当我点击第二页时,s变为了s=44,可见页数是以44位倍数的(也不知道是不是普遍如此)
所以我们要构建所有商品的信息页就可以写成:
start_urls = []
#根据指定页数添加商品列表,设定值为20页
for i in range(0,20):
url="https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=python%E4%B9%A6%E7%B1%8D&suggest=history_1&_input_charset=utf-8&wq=p&suggest_query=p&source=suggest&sort=sale-desc&bcoffset=0&p4ppushleft=%2C44&s="+str(i*44)
start_urls.append(url)
start_urls是spider会自动爬取的url列表,所以我们只需要先把所有的url放入此列表就可以了
当然这还只是爬取了商品的所有搜索界面的信息,并不是每个商品的完整信息,所以我们接下来要做的应该是继续提取url,来访问每个商品的具体购买界面,然后提取更详细的信息。
之后我会慢慢更新代码的具体作用和内容的
以下为全部的代码(这里我们以爬取所有Python书籍的商品为例)
import scrapy
from scrapy.spiders import CrawlSpider
from selenium import webdriver
import re,requests
#构建评论页表
def makeURL(itemId,sellerId,i):
url='http://rate.tmall.com/list_detail_rate.htm?itemId='\
+itemId+'&sellerId='+sellerId+'¤tPage='+i
return url
class taobaospider(CrawlSpider):
name = "taobao"
start_urls = [
"https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=python%E4%B9%A6%E7%B1%8D&suggest=history_1&_input_charset=utf-8&wq=p&suggest_query=p&source=suggest&sort=sale-desc&bcoffset=0&p4ppushleft=%2C44&s=0"
]
#根据指定页数添加商品列表,设定值为20页
for i in range(1,2):
url="https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=python%E4%B9%A6%E7%B1%8D&suggest=history_1&_input_charset=utf-8&wq=p&suggest_query=p&source=suggest&sort=sale-desc&bcoffset=0&p4ppushleft=%2C44&s="+str(i*44)
start_urls.append(url)
def parse(self, response):
#需要通过selenium启动虚拟浏览器,如果使用其他浏览器需作出修改
driver=webdriver.Chrome()
driver.get(response.url)
driver.implicitly_wait(30)
driver.refresh()
driver.implicitly_wait(30)
html = driver.page_source
driver.close()
#添加访问商品详细界面的url
list=re.findall('href=\"//detail.tmall.com.*?\"', html)
linkList = sorted(set(list), key=list.index)
#添加销量数据
sales=re.findall('>[0-9]*人收货', html)
i=0
for href in linkList:
link = 'https:'+href.split('"')[1]
sale=sales[i].replace('>', '').replace("人收货", "")
i=i+1
yield scrapy.Request(url=link, meta={'sales':sale}, callback=self.parse_item)
def parse_item(self, response):
#根据实际item名称修改此处
item = GameItem()
#获取商品销量
item['sales']=response.meta['sales']
#从商品界面提取信息以构建评论界面的url
try:
str1 = re.findall('itemId:\".*?\"', response.text)[0]
itemId = str1.split(' ')[1]
str2 = re.findall('sellerId:\".*?\"', response.text)[0]
sellerId = str2.split(' ')[1]
except:
return
#初始化评论列表
comments = []
comment_times = []
#爬取所需评论页数,设定值为爬取100页,如果没有评论则结束
for i in range(1,2):
try:
url_comment = makeURL(itemId, sellerId, str(i))
page=requests.get(url_comment)
page.status_code
comment = re.findall('\"rateContent\":(\".*?\")', page.text)
comment_time=re.findall('\"rateDate\":(\".*?\")', page.text)
comments.extend(comment)
comment_times.extend(comment_time)
except:
break
#输入评论
item['comment'] = comments
item['comment_time'] = comment_times
#获取商品其他信息,(以@为分割符)
details=response.xpath('//ul[@id="J_AttrUL"]/li/text()').extract()
details="@".join(details)
details=details+"@"
#输入item
try:
item['name']=re.findall('书名:(.*?)@',details)[0].replace('书名:', '').replace("\xa0","")
except:
pass
try:
item['ISBN']=re.findall('ISBN编号:(.*?)@',details)[0].replace('ISBN编号:', '').replace("\xa0","")
except:
pass
try:
item['writer']=re.findall('作者:(.*?)@',details)[0].replace('作者:', '').replace("\xa0","")
except:
pass
try:
item['price']=re.findall('定价:(.*?)@',details)[0].replace('定价:', '').replace("\xa0","")
except:
pass
try:
item['company'] = re.findall('出版社名称:(.*?)@', details)[0].replace('出版社名称:', '').replace("\xa0","")
except:
pass
yield item