使用selenium和beautifulsoup通过无限滚动来刮取网站返回重复元素

时间:2017-07-01 14:55:39

标签: python selenium web-scraping beautifulsoup

所以我的脚本使用Selenium和BeautifulSoup来抓取这个网站: ' http://m.1688.com/page/offerlist.htmlspm=a26g8.7664812.0.0.R19GYe&memberId=zhtiezhi&sortType=tradenumdown'

但我的脚本会继续打印页面的前8个元素,并忽略滚动时出现的内容。这是脚本:

# -*- coding: utf-8 -*-
from urllib import urlopen
from bs4 import BeautifulSoup as BS
import unicodecsv as ucsv
import re 
from selenium import webdriver
import time 

with open('list1.csv','wb') as f:
w = ucsv.writer(f, encoding='utf-8-sig')

driver = 
webdriver.Chrome('C:\Users\V\Desktop\PY\web_scrape\chromedriver.exe')
base_url = 'http://m.1688.com/page/offerlist.html?
spm=a26g8.7664812.0.0.R19GYe&memberId=zhtiezhi&sortType=tradenumdown'
driver.get(base_url)
pageSource = driver.page_source
lst = []
for n in range(10): 
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    soup = BS(pageSource, 'lxml')
    container = soup.find('div', {'class' : 'container'})
    items = container.findAll('div', {'class' : 'item-inner'})
    for item in items:
        title = item.find('div', {'class' : 'item-price'}).text
        title_ = ''.join(i for i in title if ord(i) < 128  if i != '\n')
        lst.append(title_)
    print lst
    time.sleep(5)

每个滚动的输出是:

[u'0.21', u'0.45', u'1.10', u'3.60', u'2.20', u'6.80', u'1.40', u'3.00']
[u'0.21', u'0.45', u'1.10', u'3.60', u'2.20', u'6.80', u'1.40', u'3.00', u'0.21', u'0.45', u'1.10', u'3.60', u'2.20', u'6.80', u'1.40', u'3.00']
[u'0.21', u'0.45', u'1.10', u'3.60', u'2.20', u'6.80', u'1.40', u'3.00', u'0.21', u'0.45', u'1.10', u'3.60', u'2.20', u'6.80', u'1.40', u'3.00', u'0.21', u'0.45', u'1.10', u'3.60', u'2.20', u'6.80', u'1.40', u'3.00']

第一个滚动列表有8个元素,第二个滚动列表有16个元素,额外的8个元素从第一个滚动重复。其余卷轴也会发生同样的事情。 因此,即使我使用selenium滚动网站,脚本也只返回8个元素,但我希望它在滚动时打印出所有元素。如果你们给我一些建议,我将非常感激。

3 个答案:

答案 0 :(得分:1)

问题出在这一部分:

items = container.findAll('div', {'class' : 'item-inner'})
    for item in items:
        title = item.find('div', {'class' : 'item-price'}).text
        title_ = ''.join(i for i in title if ord(i) < 128  if i != '\n')
        lst.append(title_)

每次“滚动”时,items对象变成一个更大的块,因为滚动时,上面的内容不会消失。 您需要从n-1中删除第一个item items以避免重复。

答案 1 :(得分:0)

有两种可能性:

  1. 让无限滚动完成,然后获取数据;
  2. 每次重新加载内容后,您可以将已有的数据与新数据进行比较,然后将其添加到列表中。

答案 2 :(得分:0)

我找到了问题的答案,将pageSource放入循环中,而不是将Chrome隐藏在任务栏中,您必须打开它,或者您可以使用PhantomJS而不是Chrome驱动程序。

for n in range(10):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
pageSource = drive.page_source
soup = BS(pageSource, 'lxml')
container = soup.find('div', {'class' : 'container'})
items = container.findAll('div', {'class' : 'item-inner'})
for item in items:
    title = item.find('div', {'class' : 'item-price'}).text
    title_ = ''.join(i for i in title if ord(i) < 128  if i != '\n')
    lst.append(title_)
print len(lst)

现在输出将改变,而不是

8
8
8
8

会打印

16
20
28
...