最近需要从网上搜集一些数据,于是花了几个小时把爬虫学了一下。其实我在两年前的一个简单的站内搜索引擎的实现已经涉及到了简单的爬虫,不过那时候老想着偷懒,加上山大新闻网的设计又很好爬,所以当时写得很low,因而有网友问我要爬虫代码的时候也没好意思给。今天翻了一下韦玮老师的精通Python网络爬虫,一口气看了前六章,就想写一个简单的爬虫来练习一下。书中有一个爬取京东的手机图片的例子,我只好来爬笔记本电脑了。本意是想爬一下笔记本电脑的价格,做一个统计分析出来的,结果发现京东上面商品的价格是通过JS来获取的,可我不太懂JS,然后掂量了一下自己这几个小时的爬虫功底……就又开始偷懒了,于是乎改成了爬取笔记本电脑的图片和名字。给这篇文章的定位,大概是相当于一个课后小作业的形式,还望各位高手不要笑话。下面来介绍这个实现过程。
首先,在浏览器中打开京东的笔记本电脑商品页面
我们需要寻找有关笔记本电脑商品网页的规律。拖到页面底部,我们发现,京东有关笔记本电脑商品信息的页面总共有900多页。
分析这些页面的规律可以发现它们的URL是有规律的,下面是第2页的网址,其中有个 page=2 ,我们发现如果想转到第 x页,只需要把下面网址中的2变换为 x 就可以了。
https://list.jd.com/list.html?cat=670,671,672&page=2&sort=sort_totalsales15_desc&trans=1&JL=6_0_0#J_main
接下来,分析网页的代码。按F12打开开发者工具调试界面。
在element中找到与商品信息有关的代码部分,可以看出其id是plist,据此写出正则表达式:
pattern1 = '<div id="plist"((.|\n)+?)<div class="page clearfix">'
然后就可以提取出与商品有关的代码:
pattern1 = '<div id="plist"((.|\n)+?)<div class="page clearfix">'
goods = re.compile(pattern1).findall(html1)
goods = goods[0]
goods = goods[0]
接下来,查找每一个商品单元格对应的代码,可以发现每一个商品格子都对应一个gl-item的<li>
据此,将其从前面得到的goods中提取出来:
item_pattern = '<li class="gl-item">((.|\n)+?)</li>'
compute_list = re.compile(item_pattern).findall(goods)
提取出来之后的compute_list是一个list的形式,其中的每个元素对应一个商品格的代码。接下来我们需要对每一个商品格的代码进行分析,从中提取出图片的地址和笔记本电脑的名称。方法与前面相似:
compute_str = compute[0]
# 提取图片
image_pattern = '<img width="220" height="220" data-img="1" src="//(.+?\.jpg)'
image_url = re.compile(image_pattern).findall(compute_str)
image_url = image_url[0]
image_url = "http://" + image_url # 图片网址
# 提取商品名称
name_div_pattern = '<div class="p-name">((.|\n)+?)</div>'
name_div = re.compile(name_div_pattern).findall(compute_str)
name_div = name_div[0]
name_div_str = name_div[0]
name_pattern = '<em>\n(.+?)</em>'
name = re.compile(name_pattern).findall(name_div_str)
name = name[0]
这样就成功地提取到了一种笔记本的图片地址和名称。接下来我们只需要加一个万能的for循环,就可以获取所有的笔记本的图片地址和商品名了。全部代码如下所示:
import re
import urllib.request as request
import urllib
def craw(url, page, save_path):
"""
爬取京东笔记本电脑的图片和名称
:param url: 网址
:param page:
:param save_path: 存储路径
:return:
"""
html1 = request.urlopen(url).read().decode('utf-8')
pattern1 = '<div id="plist"((.|\n)+?)<div class="page clearfix">'
goods = re.compile(pattern1).findall(html1)
goods = goods[0]
goods = goods[0]
item_pattern = '<li class="gl-item">((.|\n)+?)</li>'
compute_list = re.compile(item_pattern).findall(goods)
index = 1
for compute in compute_list:
try:
compute_str = compute[0]
# 提取图片
image_pattern = '<img width="220" height="220" data-img="1" src="//(.+?\.jpg)'
image_url = re.compile(image_pattern).findall(compute_str)
image_url = image_url[0]
image_url = "http://" + image_url # 图片网址
# 提取商品名称
name_div_pattern = '<div class="p-name">((.|\n)+?)</div>'
name_div = re.compile(name_div_pattern).findall(compute_str)
name_div = name_div[0]
name_div_str = name_div[0]
name_pattern = '<em>\n(.+?)</em>'
name = re.compile(name_pattern).findall(name_div_str)
name = name[0]
image_path = save_path + "Page" + str(page) + "-" + str(index) + name + ".jpg"
try:
request.urlretrieve(image_url, filename=image_path)
except urllib.error.URLError as e:
if hasattr(e, "code"):
index += 1
if hasattr(e, "reason"):
index += 1
except Exception as e:
continue
index += 1
def run():
url = "https://list.jd.com/list.html?cat=670,671,672&page=1&sort=sort_totalsales15_desc&trans=1&JL=6_0_0#J_main"
save_path = "E:\\Project\\Spider\\JDcomputes\\"
for i in range(1, 962):
url = "https://list.jd.com/list.html?cat=670,671,672&page=" + str(i)
url = url + "&sort=sort_totalsales15_desc&trans=1&JL=6_0_0#J_main"
craw(url, i, save_path)
if i % 50 == 0:
print(i)
if __name__ == '__main__':
run()
最终爬取的结果如下所示:
可见,总共爬取到了4566个电脑的信息。
这个小demo由于链接的规律比较简单,还没有涉及到链接分析等内容,因而只是一个用来体验一下爬虫的小实验吧。