最近一段时间试着爬取了返利网的【今日值得买网页】http://zhide.fanli.com/p1?spm=global.pc.buid-todayworth
在这想要爬取商品名称、分类、推荐人、商品简介、好评数、差评数
1、找到源代码:
首先返利网的网页是动态的,一个网页共有50个商品,平均每次加载5个,前五个可以直接在该网页查看源代码,后面的就得自己找了,因为之前有爬过网易,所以以为它网页与网易一样是json加载,然而当用一样的方法找时并没有找到,无奈只好把每个类型都试一下,最后发现了是XHR类型的,如下:
打开之后并不是代码,而是:
要查看源代码:
2、网址规律:
因为要多页爬取,所以要先观察网址规律:
#其中pageIndex1为页数,pageIndex2为以每5个为一组的组数
url2='http://zhide.fanli.com/index/ajaxGetItem?cat_id=0&tag=&page='+str(pageIndex1)+'-'+str(pageIndex2)+'&area=0&tag_id=0&shop_id=0'
因为有两个不定数,所以要进行两个for循环。
3、筛选数据:
想了三种方法,但都有缺陷,希望各位能给一些建议:
(1)用正则表达式
reg1=r'<a class="J-item-track nodelog(.*?)>(.*?)<span class="red t-sub">(.*?)'\
r'<div class="item-type">(.*?)<a href="(.*?)/cat-(.*?)" class="nine" target="_blank">(.*?)</a></div>' \
r'<div class="item-user">(.*?)</div>(.*?)'\
# r'<a href="javascript:void(0);" class="l item-vote-yes J-item-vote-yes" data-type="yes">(.*?)</a>' \
# r'<a href="javascript:void(0);" class="l item-vote-no J-item-vote-no" data-type="no">(.*?)</a>'
fd=open('flw(1).txt','a+')
fd.write('商品名称'+'|'+'分类'+'|'+'推荐人'+'\n')
data=re.findall(re.compile(reg1),html)
for item in data:
fd.write(item[1]+'|'+item[6]+'|'+item[7]+'\n')#+'|'+'|'+item[8]+'|'+item[9]
这个缺陷在于好评数和差评数获取不到
(2)用BeautifulSoup直接筛选出商品信息,然后将不需要的信息删除。
html=re.sub('<span class="red t-sub">(.*?)</span>','',html)
html=re.sub('<div class="item-img">(.*?)</div>','',html)
html=re.sub("<i class='lowest-network'>全网最低</i>","",html)
html=re.sub('<div class="item-time">(.*?)</div>','',html)
html=re.sub('<div class="item-type">分类:<a href=(.*?)target="_blank">','',html)
html=re.sub('<div class="item-label">标签:','',html)
html=re.sub('<a href="/shop/(.*?)" target="_blank">(.*?)</a>','',html)
html=re.sub('<a href="javascript:(.*?)展开全文 ∨</a>','',html)
soup=BeautifulSoup(html)
data=soup.find_all('div',class_='zdm-list-item J-item-wrap item-no-expired')
for item in data:
fd.write(item.get_text('|',strip=True).encode('utf-8')+'\n')
这个只能的得到商品名称,分类,推荐人,评论
貌似是在我去掉后四个信息时,好评和差评等信息也被莫名的去掉了。
(3)用BeautifulSoup的按类名搜索
soup=BeautifulSoup(html)
mc=soup.find_all('a',class_='J-item-track nodelog')
fl=soup.find_all('div', class_="item-type")
tjr=soup.find_all('div',class_='item-user')
pl=soup.find_all('div', class_='item-content-inner J-item-content-inner')
yes=soup.find_all('a',class_='l item-vote-yes J-item-vote-yes')
no=soup.find_all('a',class_='l item-vote-no J-item-vote-no')
for i in range(0,5):
print mc[i].get_text(strip=True).encode('utf-8')+'|'+\
fl[i].get_text(strip=True).encode('utf-8')+'|'+\
tjr[i].get_text(strip=True).encode('utf-8')+'|'+\
pl[i].get_text(strip=True).encode('utf-8')+'|'+\
yes[i].get_text(strip=True).encode('utf-8')+'|'+\
no[i].get_text(strip=True).encode('utf-8')
这个可以把商品名称,分类,推荐人,评论,好评数,差评数 都爬下来,但它会出错啊
错误为IndexError: list index out of range,列表索引超出范围,但我想表示宝宝没有啊!!
好吧,说我超出范围,我改为
for i in range(0,3)
这下虽然能够保证不出错,但爬下来的明显数量不够,因为每次该是5个,所以我才弄成(0,5),改为(0,3)肯定会少的,无语。。
所以,以上三个都有bug,希望能得到高人指点。
其实还可以根据自己的需求修改,获取自己想要的信息
4、代码如下:
#coding=utf-8
import urllib2
import re
import time
from bs4 import BeautifulSoup
class FLW():
def __init__(self):
self.user_agent= 'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)'
self.headers = {'User_Agent' :self.user_agent}
def getUrl(self,pageIndex1,pageIndex2):
url='http://zhide.fanli.com/index/ajaxGetItem?cat_id=0&tag=&page='+str(pageIndex1)+'-'+str(pageIndex2)+'&area=0&tag_id=0&shop_id=0'
return url
def getHtml(self,url):
try:
request=urllib2.Request(url,headers=self.headers)
response=urllib2.urlopen(request)
html=response.read()
return html
except urllib2.URLError,e:
if hasattr(e,'reason'):
print u'链接失败',e.reason
return None
=======================================================================================================================
#方法一:
def getPage(self):
reg1=r'<a class="J-item-track nodelog(.*?)>(.*?)<span class="red t-sub">(.*?)'\
r'<div class="item-type">(.*?)<a href="(.*?)/cat-(.*?)" class="nine" target="_blank">(.*?)</a></div>' \
r'<div class="item-user">(.*?)</div>(.*?)'\
# r'<a href="javascript:void(0);" class="l item-vote-yes J-item-vote-yes" data-type="yes">(.*?)</a>' \
# r'<a href="javascript:void(0);" class="l item-vote-no J-item-vote-no" data-type="no">(.*?)</a>'
for x in range(1,51):#循环页数
for y in range(2,11):#循环每组
fd=open('flw(1).txt','a+')
fd.write('商品名称'+'|'+'分类'+'|'+'推荐人'+'\n')
url=self.getUrl(x,y)
html=self.getHtml(url)
html=re.sub(' ','',html)
data=re.findall(re.compile(reg1),html)
for item in data:
fd.write(item[1]+'|'+item[6]+'|'+item[7]+'\n')#+'|'+item[8]+'|'+item[9]
fd.close()
time.sleep(1)
=======================================================================================================================
#方法二:
def pageSX(self,html):
html=re.sub('<span class="red t-sub">(.*?)</span>','',html) #去掉商品名称里的多余信息
html=re.sub('<div class="item-img">(.*?)</div>','',html) #去掉“返利多少”的信息
html=re.sub("<i class='lowest-network'>全网最低</i>","",html) #去掉“全网最低”
html=re.sub('<div class="item-time">(.*?)</div>','',html) #去掉时间信息
html=re.sub('<div class="item-type">分类:<a href=(.*?)target="_blank">','',html)
html=re.sub('<div class="item-label">标签:','',html)
html=re.sub('<a href="/shop/(.*?)" target="_blank">(.*?)</a>','',html)
html=re.sub('<a href="javascript:(.*?)展开全文 ∨</a>','',html)
soup=BeautifulSoup(html)
data=soup.find_all('div',class_='zdm-list-item J-item-wrap item-no-expired')#直接获取商品所有信息
return data
def getPage(self):
for x in range(1,51):
for y in range(2,11):
fd=open('flw(2).txt','a+')
fd.write('商品名称'+'|'+'分类'+'|'+'推荐人'+'|'+'评论'+'\n')
url=self.getUrl(x,y)
html=self.getHtml(url)
data=self.pageSX(html)
for item in data:
fd.write(item.get_text('|',strip=True).encode('utf-8')+'\n')
fd.close()
time.sleep(1)
=======================================================================================================================
方法三:
def pageSX(self,html):
html=re.sub('<div class="item-label">标签:(.*?)</a></div>','',html)
html=re.sub('<span class="red t-sub">(.*?)</span>','',html)
soup=BeautifulSoup(html)
mc=soup.find_all('a',class_='J-item-track nodelog') #获取商品名称
fl=soup.find_all('div', class_="item-type") #获取分类
tjr=soup.find_all('div',class_='item-user') #获取推荐人
pl=soup.find_all('div', class_='item-content-inner J-item-content-inner') #获取商品简介
yes=soup.find_all('a',class_='l item-vote-yes J-item-vote-yes') #获取好评数
no=soup.find_all('a',class_='l item-vote-no J-item-vote-no') #获取差评数
fd=open('flw(3).txt','a+')
for i in range(0,3):
fd.write(mc[i].get_text(strip=True).encode('utf-8')+'|'+\
fl[i].get_text(strip=True).encode('utf-8')+'|'+\
tjr[i].get_text(strip=True).encode('utf-8')+'|'+\
pl[i].get_text(strip=True).encode('utf-8')+'|'+\
yes[i].get_text(strip=True).encode('utf-8')+'|'+\
no[i].get_text(strip=True).encode('utf-8'))
fd.close()
def getPage(self):
for x in range(1,51):
for y in range(2,11):
url=self.getUrl(x,y)
html=self.getHtml(url)
self.pageSX(html)
time.sleep(1)
=======================================================================================================================
spider=FLW()
SJ=spider.getPage()
以上
PS:想说并不怎么理想,希望以后可以将遇到的问题解决,再来完善!
已经做了修改,具体修改请看下一篇点击打开链接