前言
接下来的一段时间里,将完成一个爬虫系列文章,各位请慢慢看,也请慢慢点赞
这一节先讲讲大致工具和目标吧
1 目标和工具
作为菜鸟先从爬图片入手吧,下手目标就是 <a href="http://www.mafengwo.cn">蚂蜂窝旅游网站</a>
爬虫工具用我们的老朋友scrapy
配置python版本用 virtualenv 比较方便使用
命令
virtualenv -p c:\Python36\python.exe HigEnv #windows7
2 基本步骤
1.创建scrapy工程
cmd cd到合适目录下,输入命令
scrapy startproject mafengwoscrapy
这样就在当前目录下创建了mafengwoscrapy这个工程
2.创建一个spider
在mafengwoscrapy工程下的spiders 目录下创建一个 mafengwospider.py文件
注释写的比较清楚可以直接看
# -*- coding: utf-8 -*-
import os
import urllib
from queue import Queue
from urllib import request
import scrapy
from scrapy import Selector, Request
import re
class MafengwospiderSpider(scrapy.Spider):
name = 'mafengwospider'
#开始爬取的网站
start_urls = ['http://www.mafengwo.cn/mdd/']
code_citymap = {}
def parse(self, response):
if response.url == 'http://www.mafengwo.cn/mdd/':
#这是根据页面的来进行xpath匹配
#这一步的目的是爬取mafengwo网站所有的国内城市和对应的code
extract = response.xpath("//div[@class='hot-list clearfix']").xpath(".//a").extract()
#正则表达式提取城市code
pattern = re.compile(r"/(\d*?).html")
for ahtmltext in extract:
#将html格式的字符串进行xpath筛选的方法
code_place = Selector(text=ahtmltext).xpath("//a/@href|//a/text()").extract()
if len(code_place) == 2:
code = pattern.findall(code_place[0])
self.code_citymap[code[0]] = code_place[1]
print(self.code_citymap)
#将城市code放入队列
#采取深度优先的策略爬取
self.codes = Queue()
for a in self.code_citymap.keys():
self.codes.put(a)
citycode = self.codes.get()
#注意下,这个http://www.mafengwo.cn/yj/%s/1-0-1.html的url是mafengwo网站每一个城市的游记列表的入口
#meta用来标识请求来源和请求额外参数很方便
yield Request(url=r"http://www.mafengwo.cn/yj/%s/1-0-1.html" % (citycode),
meta={"code": citycode, "type": "list"})
##判断请求是城市游记文章列表页
elif response.meta["type"] == "list":
code = response.meta["code"]
if 'pageindex' not in response.meta:
pageindex = 1;
else:
pageindex = response.meta["pageindex"]
pageindex += 1
#这个xpath能筛选出该页所有的文章信息
extract = response.xpath(
r"//li[@class='post-item clearfix']/div[@class='post-cover']/a/@href"
).extract()
if len(extract) > 0:
#爬取分页中的每一篇文章
for followurl in extract:
yield response.follow(url=followurl, priority=20,
meta={"code": code, "type": "article"})
#每个城市只爬到第2页
if (pageindex <=2):
yield response.follow(
url="http://www.mafengwo.cn/yj/%s/1-0-%s.html" % (code, pageindex),
priority=10,meta={"code": code, "type": "list", "pageindex": pageindex}
)
#爬下一个城市
elif not self.codes.empty():
citycode = self.codes.get()
yield Request(url=r"http://www.mafengwo.cn/yj/%s/1-0-1.html" % (citycode),
meta={"code": citycode, "type": "list"})
#当前城市返回空,爬下一个城市
elif not self.codes.empty():
citycode = self.codes.get()
yield Request(url=r"http://www.mafengwo.cn/yj/%s/1-0-1.html" % (citycode),
meta={"code": citycode, "type": "list"})
#判断请求的是文章详情页
elif response.meta["type"] == "article":
code = response.meta["code"]
htmlname = response.url.split("/")[-1].replace(r".html", "")
#提取出该文章中所有的图片链接
images = response.xpath(
"//img[@class='_j_lazyload _j_needInitShare']/@data-src").extract()
if len(images) == 0:
print(htmlname + " failed")
for i in range(len(images)):
#所有图片下载到本地
print(images[i])
filedir = "E:/images/mafengwo/%s" % (self.code_citymap[code])
if not os.path.exists(filedir):
os.makedirs(filedir)
imagefilepath="%s/%s_%s.jpg" % (filedir, htmlname, i)
if not os.path.exists(imagefilepath):
#python3 urllib下载简单图片或者文件的方法
req=urllib.request.Request(images[i])
with urllib.request.urlopen(req,timeout=10) as f:
with open(imagefilepath,"wb") as writef:
writef.write(f.read())
整体的爬虫代码需要结合网页的源码看,没什么细节的就不多说了,另外在工程目录
的settings.py中,改下参数
# 设置为不遵守robot协议
#以及每次scrapy request 请求最小间隔为1s,防止被反爬虫
ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = 1
3.启动爬虫
爬虫启动很简单的,cd 到 mafengwoscrapy工程目录下执行
scrapy crawl mafengwospider 即可
4.结果
爬取的速度不是很快,结果如截图所示