python爬虫08-selenium爬取淘宝网商品(源码)
昨天之所以水了,是因为日更30天了,歇一歇,同时也是为了完成今天的这个爬虫,毕竟第一次使用selenium+chrome爬取网站。
前两天写分析ajax爬虫,是分析了网站请求的参数、请求地址、上传的表单,模拟浏览器访问页面来的到源码,但是有时候ajax的参数非常多,而且经过加密,很难找到规律。这时候我们就需要使用selenium这个强大的库了,它可以控制浏览器,模拟人的操作,直接获取浏览器渲染完成后的页面源码,真正做到可见即可爬。
不多说,让我们开始吧!
selenium需要我们配合浏览器使用,它支持很多款浏览器,但是我更喜欢chrome,因为它调试起来更方便,就像很多前段程序猿也喜欢chrome一样,反正我不喜欢IE,让它当场去世吧!
chromeDriver 也是必需品。下载下来后放在环境的script文件下。
这次也是,还是剩下一小部分没完成,现在还没学习到。之后会完善。
- 搜索商品后会直接跳到登录界面,所以我直接打开的登录界面,现在我只能扫码登陆,账号密码登陆会出滑动验证码,这在ChromeDriver里无法完成,我就直接等10s让我扫码登陆了。
其实吧我感觉爬虫没什么好讲的,主要是对抗反爬机制能够给我带来快乐。这次淘宝的反爬很厉害。换页的速度不能太快,太快的话,到18页就会被要求进行滑动验证,但是由于浏览器问题,总是失败。所以我在换页之前用了10s的延时才能全部爬下来。
一共爬了100页,我输入的‘ipad’,一共4404条数据,全部存在数据库中,方便以后使用:
image.png 结果[图片上传失败...(image-e5e97b-1553952994597)]
这次的程序中设计等待时间的概念,一个是隐式等待,一个是显示等待。
隐式等待就是等待给定的时间,在寻找页面中的元素,如果时间到了还没加载出来,就报错,这一般用的少,但这次我也用了,在扫码登录的时候。
显示等待是指如果再规定的时间内加载出来了,就获取节点,如果没有加载出来报错。
代码不长,具体内容就不讲了,没意思。你爬虫遇到问题了,来对比下,找找不同,这样才能得到最大的进步,什么都直接说出来,就没有找答案的这个过程,也就没有任何的成就感,而且我写这个,只是我为了记录自己的学习过程。最终虽然得到了我想要的,但反爬机制没解决,感觉得到之后一切都变得索然无味。
还有就是浏览器滑动验证这一点,这将是我接下来的学习方向,之后就可以为所欲为了。
import re
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pyquery import PyQuery as pq
from config import *
import pymongo
# chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument()
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
client = pymongo.MongoClient(MONGODB_HOST, MONGODB_POST)
db = client[MONGODB_DB]
collection = db[MONGODB_COLLECTION]
def login():
print("正在登录")
# 需要用手机淘宝扫二维码登录才能搜索
browser.get(url='https://login.taobao.com')
# 10s用来扫码登录
browser.implicitly_wait(10)
def search():
print("正在查找",KEYWORD)
try:
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()
total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,
"#mainsrp-pager > div > div > div > div.total")))
get_goods()
return total.text
except TimeoutError:
return search()
def next_page(page_number):
print("正在换页", page_number)
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()
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)))
get_goods()
except Exception:
next_page(page_number)
def get_goods():
try:
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,
'#mainsrp-itemlist .items '
'.item')))
html = browser.page_source
doc = pq(html)
items = doc('#mainsrp-itemlist .items .item').items()
for item in items:
goods = {
'img': item.find('.pic .img').attr('data-src'),
'price': item.find('.price').text(),
'deal': item.find('.deal-cnt').text(),
'title': item.find('.title').text(),
'shop': item.find('.shop').text(),
'location': item.find('.location').text()
}
save_to_mongodb(goods)
except Exception:
print("获取商品失败")
def save_to_mongodb(result):
try:
if db[MONGODB_COLLECTION].insert_one(result):
print("存储到数据成功", result)
except Exception:
print("存储到数据库失败", result)
def main():
login()
total = search()
total = int(re.compile('(\d+)').search(total).group(0))
for i in range(2, total + 1):
if i % 15 == 0:
time.sleep(20)
next_page(i)
if __name__ == '__main__':
main()
在使用前一定要记得把该装的库都装了,数据库打开,网络通畅。
得抓紧学习了,要赶在工大春招之前学完。
之前在百度贴吧帮别人解决问题,这让我很开心,忘记了时间。所以今天晚了点。