目前爬虫基本思想就是进入一个网站商品列表页并进入具体商品链接,爬取商品详情。这次选择的是国内某知名生活服务网站。一段时间的学习后,运用chrome寻找需求元素已能得心应手,但是实际操作中依然遇到一些问题。
主要问题
- 在商品详情页中,不同来源类型的商品有不同的css样式,这使得select()不能直接适用,因此在商品列表页需要进行将爬取的商品详情链接分为两类,分别爬取。
- 在其中一类,个别需要爬取的信息中是通过js的方式查看的,需要通过不同的方式获取这部分的内容
- 个别字符串信息的处理出现了一些问题
最终效果
在sublime python编译环境下爬取的一页数据,一共有三十七个商品,但是有时js获取点击量(hit)的方法会行不通。
我的代码
在sublime 的python环境下爬取了一页商品信息,一共有37个。保存在dict中,以方便之后在数据库中的操作。
# -*- coding: utf-8 -*-
import requests,time
from bs4 import BeautifulSoup
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
def main():
url='***********'
web=requests.get(url,headers=headers)
soup=BeautifulSoup(web.text, 'lxml')
hrefs_zz=soup.select(' tr.zzinfo td.img a') #所有链接
hrefs_jz=soup.select(' tr.zzinfo.zzjingzhun td.img a') #精准推广的链接
count=0 #为每个商品info计数
if hrefs_zz: #是不是为空
print len(hrefs_zz)
for href in hrefs_zz:
#print href
count=count+1
print count, '--->'
link=href.get('href')
getsingle_info(link)
time.sleep(2)
else:
print 'heheha'
def getsingle_info(href): #zz下
web=requests.get(href,headers=headers)
soup=BeautifulSoup(web.text, 'lxml')
#titles=soup.title.text # 网页title标签内容与商品详情标签相同
titles=soup.select(' h1.info_titile ')
if titles:
pass
else:
get_jzsingle_info(href)
return
cates=soup.select('.breadCrumb > span')
prices=soup.select('span.price_now > i')
addrs=soup.select('div.palce_li > span > i')
hits=soup.select('.look_time')
data={
'cate': [cates[i].get_text().strip() for i in range(len(cates))], #s.strip(rm) rm为空时,默认删除空白(\r \n \t)
#cate[i].stripped_strings不对其列表化时 返回的就是一个内存对象
'title': titles[0].text,
'price': prices[0].text,
'addr': addrs[0].text,
'hit': hits[0].text
}
print data,'\n------------------\n'
def get_jzsingle_info(url):
web=requests.get(url,headers=headers)
soup=BeautifulSoup(web.text, 'lxml')
cates=soup.select('.breadCrumb > span')
#print cates,'\n'
titles=soup.select('.col_sub.mainTitle > h1')
#print titles,'\n'
prices=soup.select('span.price.c_f50 ')
#print prices,'\n'
addrs=soup.select('span.c_25d > a ')
hits=soup.select(' #totalcount ')
#print addrs, '\n'
data={
'cate': [cates[i].get_text().strip() for i in range(len(cates))],
'title': titles[0].text if titles else None,
'price': prices[0].text if prices else None,
'addr': addrs[0].text if addrs else None,
'hit': gethits(url)
}
print data,'\n------------------\n'
def gethits(url):
keyword=url.split('/')[-1].strip('x.shtml') #得到每个商品的id
api='***********r?infoid={}'.format(keyword)
headers={'Referer': url}
js= requests.get(api,headers=headers)
hits=js.text.split('=')[-1]
return hits
if __name__ == '__main__':
main()
总结
- 网页元素中运用class 与 id 可以唯一寻找,并且可以不用 > 来更快的选择子类标签
- 由于存在两种类型的商品详情页面,我的思路是如果其中一种select()方式选择的为空list,就进入另一个爬取商品信息函数。这样做的好处是分别获得不同商品类型的信息而不是None
- js 中的内容是根据api来获得的 ,还需要添加一个referer(来源地址),为了网站的反爬取,同时需要伪装成浏览器。
- 学习了strip() 与 split() 两个字符串处理函数