之前爬取过一次淘宝的商品,直接使用slenium就可以直接爬取信息,这次又想再次爬取一下信息,发现每次爬取的信息都不全,纠结啊!
(一)首先,介绍下背景:
这次爬取的选择是手机。打开淘宝,搜索手机,可以发现每页商品共有48个,一共100页。
(二)流程介绍
首先确定使用的爬取方式(这里使用selenium),然后是页面分析,标签定位,最后确定信息的存储方式(这里为了方便直接打印), 最后的最后就是程序的编写了。
(三)程序编写
页面分析,标签定位这些就不再详细介绍了,直接说程序的编写了。编写好程序之后,就是运行了。然而运行的时候,发现了一个问题,每页提取出来的信息远远少于每页应该有的信息(每页是48个,这里却每次大约提取了一半左右)。最初以为是程序的问题,仔细检查了几遍之后,发现都是同样的问题。因此决定把获取的网页源代码下载下来看下:
html = browser.page_source
with open("taobao.txt",'w', encoding='utf-8') as f:
f.write(html)
接下来查看源代码,
可以发现,有很大一部分商品信息没有加载出来
(四)问题分析
根据(三)可以发现,商品信息没有完全爬取的原因是:在页面信息没有完全加载的情况下,就已经把网页信息下载下来了。
接下来返回淘宝商品页面,可以发现,商品页面并不是一次加载完的。下拉面右边的进度条可以发现,在下拉的过程中,部分商品信息才加载出来。因此,可以确定要想把信息完全加载出来,还应该实现程序下拉,因此在原先程序中加入,下拉功能:
browser.execute_script('window.scrollBy(0, 1000)')
每次下来1000像素,经过测试,我的电脑只需要下拉5次就可以了,因此,下拉的全部代码如下:
while True:
if sroll_cnt < 5:
browser.execute_script('window.scrollBy(0, 1000)')
time.sleep(0.2)
sroll_cnt += 1
else:
break
每次下来后,都暂停0.2s,给加载留下反应的时间,如果网络不好,这个时间还可以加长。经过测试,这样就可以把全部信息加载出来了。
(五)源码
下面就是全部的源码了,最后的结果没有进行存储,只是打印了出来。
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from urllib import parse
from bs4 import BeautifulSoup
import time
browser = webdriver.Firefox()
wait = WebDriverWait(browser, 30)
KEYWORD = '手机'
MaxPage = 100 #最大页数
count = 0 #控制变量
sroll_cnt = 0 #下拉控制次数
def html_get(page):
"""
获取html生成
"""
global sroll_cnt
print("正在",page,'页')
url = "https://s.taobao.com/search?q=%E6%89%8B%E6%9C%BA"
browser.get(url)
try:
"""
首先寻找输入框
"""
input_p = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#spulist-pager .form>input')))
submit_p = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, '#spulist-pager .form>.btn')))
input_p.clear()
input_p.send_keys(page)
submit_p.click()
time.sleep(3)
#browser.execute_script('window.scrollBy(0, document.body.scrollHeight)')
while True:
if sroll_cnt < 5:
browser.execute_script('window.scrollBy(0, 1000)')
time.sleep(0.2)
sroll_cnt += 1
else:
break
sroll_cnt = 0 #复位
print("开始等待")
wait.until(
EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#spulist-pager .items .item.active>span'), str(page)))
print("第一个等待已经结束")
wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#spulist-grid .grid-container #J_SPUBlankRow11 .grid-item .title-row")))
get_product() #转到获取商品页面
except TimeoutException:
print("超时")
html_get(page) #超时重新调用
def get_product():
"""
获取商品信息
"""
global count
html = browser.page_source #获取商品xinxi
soup = BeautifulSoup(html,'lxml')
item_list = soup.select('#spulist-grid .grid-container .grid-item')
if count < 1:
with open('taobao.txt','w', encoding='utf-8') as f:
f.write(html)
count += 1
print(len(item_list))
for item in item_list:
try:
product = {
"name":item.select('.title-row .product-title')[0].attrs['title']
}
print(product)
except:
pass
def main():
for i in range(1, MaxPage+1):
html_get(i)
if __name__ == '__main__':
main()