Python爬虫之淘宝(一)



淘宝网也是动态加载的网页,虽然其页面数据也是通过 Ajax 获取的,但是若想像前面一样去分析 Ajax ,在淘宝这里是很复杂的,因为其参数会包含加密密钥,自己构造 Ajax 参数过于复杂。所以并不建议使用和爬取今日头条一样的方法来爬取淘宝。

先来分析下淘宝的接口,来观察 Ajax 复杂程度。

打开淘宝,再打开开发者工具,搜索关键词 python ,截获 Ajax 请求,这里看到只有一条请求,并且其内容为 json 形式的商品信息。

再来查看其构造参数。可以看到其中的 ksTS 和 rn 参数不能直接找到其规律,如果想找,只会消耗大量时间。但是如果使用 selenium 来模拟浏览器操作的话,那就不需要再关注这些参数了。因此接下来的部分使用 selenium 来爬取淘宝宝贝信息。


selenium 是一个用于 Web 应用程序测试的工具。Selenium 直接运行在浏览器中,就好像真实用户在操作一样,因此在爬虫中主要用来解决 js 渲染问题。其支持很多浏览器,常见的 Chrome, Firefox, ie,safari 和无头浏览器 phantomjs 。

这次就使用 selenium 这个工具来操作对淘宝商品的爬虫。

selenium 的使用方法步骤:首先导入所需要的包,然后声明浏览器对象,再去请求网页,最后进行查找节点等等操作。

导入所需要的包:

1
from selenium import webdriver

声明浏览器对象(使用 Chrome 浏览器):

1
browser = webdriver.Chrome()

访问网页

1
2
url = 'https://www.taobao.com'
browser.get(url)


下面来写整个项目,按照惯例,先列出步骤。

1.使用 selenium 访问淘宝商品列表网页,获取网页源代码。

2.使用网页解析工具采集所需数据。

3.导出并整理数据。


使用 selenium 获取网页源代码

1
2
3
4
5
6
7
from selenium import webdriver

browser = webdriver.Chrome()
url = 'https://s.taobao.com/search?q=python'
browser.get(url)
# 使用page_source获取网页源代码
html = browser.page_source

获取所需数据

在商品列表页中,要爬取的信息有商品图片、商品价格、商品成交量、商品名称、店铺名称和位置这六项信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq

doc = pq(html)
items = doc('#mainsrp-itemlist .items .item').items()
for item in items:
product = {
'image': item.find('.pic .img').attr('data-src').replace('//', 'http://'),
'price': item.find('.price').text().replace('\n', ''),
'deal': item.find('.deal-cnt').text(),
'title': item.find('.title').text(),
'shop': item.find('.shop').text(),
'location': item.find('.location').text()
}
print(product)

获取到以下数据。

翻页

在 index_page 中首先访问了 url ,然后判断当前页码,如果大于1,就进行跳页操作,否则等待页面加载完成。

等待加载时,使用了 WebDriverWait 对象,它可以指定等待条件,这里指定为10s,如果在这个时间内成功匹配了等待条件,就立即返回结果并向下执行,否则就抛出超时异常。

比如在这里要等待商品信息加载出来,就制定了 presence_of_element_located 这个条件,然后传入 .m-itemlist .items .item 选择器,而这个选择器对应的页面内容就是每个商品的新消息块,如果加载成功了,就会执行后续的 get_products() 方法。

关于翻页操作,这里先获取了页码的输入框,赋值为 input ,然后再获取确定按钮,赋值为 submit 。获取到两个元素后,先调用 clear() 方法将页码输入框进行清空,再调用 send_keys() 方法将页码填充进去。

那么如何确定浏览器有没有跳转到对应的页码呢,可以看到,成功跳转到某一页时,当前页码会在网页底部高亮显示,因此可以拿到高亮显示的 css 选择器与当前传入的页码做对比,如果一致,则跳转成功。继续等待商品加载完成…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from urllib.parse import quote
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

wait = WebDriverWait(browser, 10)
KEYWORD = 'python'

def index_page(page):
try:
url = 'https://s.taobao.com/search?q=' + quote(KEYWORD)
browser.get(url)
if page > 1:
# 页码输入框
input = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.form > input'))
)
# 页码确定按钮
submit = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit'))
)
input.clear()
input.send_keys(page)
submit.click()
wait.until(
EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager li.item.active > span'), str(page))
)
wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item'))
)
get_products()
except TimeoutException:
index_page(page)

保存数据到 MongoDB

1
2
3
4
5
6
7
8
client = pymongo.MongoClient('localhost', 27017)
db = client['taobao']
collection = db['taobao1_spider']


def save_to_mongo(data):
if collection.insert(data):
print('保存到MongoDB成功')

采集到的数据如下。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from selenium import webdriver
from urllib.parse import quote
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 pyquery import PyQuery as pq
import pymongo

browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
KEYWORD = 'python'
client = pymongo.MongoClient('localhost', 27017)
db = client['taobao']
collection = db['taobao1_spider']


def index_page(page):
try:
url = 'https://s.taobao.com/search?q=' + quote(KEYWORD)
browser.get(url)
if page > 1:
input = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.form > input'))
)
submit = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit'))
)
input.clear()
input.send_keys(page)
submit.click()
wait.until(
EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager li.item.active > span'), str(page))
)
wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item'))
)
get_products()
except TimeoutException:
index_page(page)


def get_products():
html = browser.page_source
doc = pq(html)
items = doc('#mainsrp-itemlist .items .item').items()
for item in items:
product = {
'image': 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()
}
print(product)
save_to_mongo(product)


def save_to_mongo(data):
if collection.insert(data):
print('保存到MongoDB成功')


def main():
for page in range(1, 101):
index_page(page)
browser.close()

if __name__ == "__main__":
main()

-------------本文结束感谢您的阅读-------------
0%