1.流程框架
淘宝页面信息很复杂的,含有各种请求参数和加密参数,如果直接请求或者分析Ajax请求的话会很繁琐。所以我们可以用Selenium来驱动浏览器模拟点击来爬取淘宝的信息。用Selenium爬取可以直接获取网页渲染后的源代码,输出page_source属性即可。这样,我们就可以做到网页的动态爬取了。缺点是速度相比之下比较慢。
2.环境须知
在进行爬取之前,需进行的准备工作是安装好selenium库,以及pyquery,mongodb,PhantomJS。浏览器我用的是Chrome,为了在python环境下驱动,又安装了ChromeDriver。简单介绍一下selenium库的作用及安装过程。
1)selenium库的作用
selenium是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。
这里要说一下比较重要的PhantomJS,PhantomJS是一个而基于WebKit的服务端JavaScript API,支持Web而不需要浏览器支持,其快速、原生支持各种Web标准:Dom处理,CSS选择器,JSON等等。PhantomJS可以用用于页面自动化、网络监测、网页截屏,以及无界面测试。
2)安装
pip install selenium 或者到https://pypi.python.org/pypi/selenium 下载setup安装包,之后进入目录后运行python setup.py install。
3.完整代码
由于Chrome版浏览器会一直跳出,所以本文使用的是PhantomJS版。
config.py文件
MONGO_URL = 'localhost'
MONGO_DB = 'taobao'
MONGO_TABLE = 'product'
SERVICE_ARGS = ['--load-images=false','--disk-cache=true']#不加载图片,开启缓存
KEYWORD = "美食"
spider.py文件
importre
fromseleniumimportwebdriver
fromselenium.webdriver.common.byimportBy
fromselenium.webdriver.support.uiimportWebDriverWait
fromselenium.webdriver.supportimportexpected_conditionsasEC
frompyqueryimportPyQueryaspq
fromconfig2import*
importpymongo
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
browser = webdriver.PhantomJS(service_args=SERVICE_ARGS)
wait = WebDriverWait(browser,10)#浏览器最长等待10秒
browser.set_window_size(1400,900)
defsearch():#搜索方法
print("正在搜索")
try:
browser.get("https://www.taobao.com")
input= wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR,"#q"))
)
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#J_TSearchForm > div.search-button > button')))
input.send_keys(KEYWORD)#向输入框输入“美食”
submit.click()#点击按钮
get_product()#调用get_product()函数获取商品信息
total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.total")))
returntotal.text#返回total的内容
exceptTimeoutError:
returnsearch()
defnext_page(page_number):#翻页方法
print("正在翻页")
try:
input= wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.form > input")))#获取搜索框
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit')))
input.clear()#清空页码输入框
input.send_keys(page_number)#输入页码
submit.click()
get_product()#调用get_product()函数获取商品信息
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > ul > li.item.active > span"),str(page_number)))
#获取当前页码并判定
exceptTimeoutError:
next_page(page_number)#出错则重新调用
defget_product():#获取商品信息方法
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-itemlist .items .item")))#获取商品信息标签
html = browser.page_source#获取网页源代码
doc = pq(html)#使用pyquery库解析
items = doc("#mainsrp-itemlist .items .item").items()#获取所有item标签
foriteminitems:
product = {#以字典形式保存数据
'image': item.find('.pic .img').attr('src'),#图片链接
'price': item.find('.price').text(),#价格
'deal': item.find('.deal-cnt').text()[:-3],
'title': item.find('.title').text(),
'shop': item.find('.shop').text(),
'location': item.find('.location').text()
}
print(product)#输出商品信息
save_to_mongo(product)#把商品信息存储到数据库
defsave_to_mongo(result):#保存到数据库的方法
try:
ifdb[MONGO_TABLE].insert(result):#把数据插入到数据库
print("存储到MONGODB成功",result)
exceptException:
print("存储到MONGODB失败",result)
defmain():#主方法
try:
total = search()
total =int(re.compile('(\d+)').search(total).group(1))
"""
result = re.compile("(\d+)")#得到数字
total = re.search(result,total).group(1)
#re.search扫描整个字符串并返回第一个成功的匹配
#因为正则里使用了(),所以使用group()获取
total = int(total)#可能是字符串,强制类型转换
"""
foriinrange(2,total +1):
next_page(i)#从2到100页翻页
print(total)
exceptException:
print("出错了.")
finally:
browser.close()#关闭浏览器
if__name__ =="__main__":
main()
代码分享完毕。使用Selenium中,记得在关键操作前加入等待判定,确保所需元素加载完成或者达到我们想要的状态。
领取专属 10元无门槛券
私享最新 技术干货