前言
接下來(lái)的一段時(shí)間里巷查,將完成一個(gè)爬蟲(chóng)系列文章有序,各位請(qǐng)慢慢看,也請(qǐng)慢慢點(diǎn)贊
這一節(jié)先講講大致工具和目標(biāo)吧
1 目標(biāo)和工具
作為菜鳥(niǎo)先從爬圖片入手吧岛请,下手目標(biāo)就是 <a >螞蜂窩旅游網(wǎng)站</a>
爬蟲(chóng)工具用我們的老朋友scrapy
配置python版本用 virtualenv 比較方便使用
命令
virtualenv -p c:\Python36\python.exe HigEnv #windows7
2 基本步驟
1.創(chuàng)建scrapy工程
cmd cd到合適目錄下旭寿,輸入命令
scrapy startproject mafengwoscrapy
這樣就在當(dāng)前目錄下創(chuàng)建了mafengwoscrapy這個(gè)工程
2.創(chuàng)建一個(gè)spider
在mafengwoscrapy工程下的spiders 目錄下創(chuàng)建一個(gè) mafengwospider.py文件
注釋寫(xiě)的比較清楚可以直接看
# -*- 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'
#開(kāi)始爬取的網(wǎng)站
start_urls = ['http://www.mafengwo.cn/mdd/']
code_citymap = {}
def parse(self, response):
if response.url == 'http://www.mafengwo.cn/mdd/':
#這是根據(jù)頁(yè)面的來(lái)進(jìn)行xpath匹配
#這一步的目的是爬取mafengwo網(wǎng)站所有的國(guó)內(nèi)城市和對(duì)應(yīng)的code
extract = response.xpath("http://div[@class='hot-list clearfix']").xpath(".//a").extract()
#正則表達(dá)式提取城市code
pattern = re.compile(r"/(\d*?).html")
for ahtmltext in extract:
#將html格式的字符串進(jìn)行xpath篩選的方法
code_place = Selector(text=ahtmltext).xpath("http://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放入隊(duì)列
#采取深度優(yōu)先的策略爬取
self.codes = Queue()
for a in self.code_citymap.keys():
self.codes.put(a)
citycode = self.codes.get()
#注意下,這個(gè)http://www.mafengwo.cn/yj/%s/1-0-1.html的url是mafengwo網(wǎng)站每一個(gè)城市的游記列表的入口
#meta用來(lái)標(biāo)識(shí)請(qǐng)求來(lái)源和請(qǐng)求額外參數(shù)很方便
yield Request(url=r"http://www.mafengwo.cn/yj/%s/1-0-1.html" % (citycode),
meta={"code": citycode, "type": "list"})
##判斷請(qǐng)求是城市游記文章列表頁(yè)
elif response.meta["type"] == "list":
code = response.meta["code"]
if 'pageindex' not in response.meta:
pageindex = 1;
else:
pageindex = response.meta["pageindex"]
pageindex += 1
#這個(gè)xpath能篩選出該頁(yè)所有的文章信息
extract = response.xpath(
r"http://li[@class='post-item clearfix']/div[@class='post-cover']/a/@href"
).extract()
if len(extract) > 0:
#爬取分頁(yè)中的每一篇文章
for followurl in extract:
yield response.follow(url=followurl, priority=20,
meta={"code": code, "type": "article"})
#每個(gè)城市只爬到第2頁(yè)
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}
)
#爬下一個(gè)城市
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"})
#當(dāng)前城市返回空崇败,爬下一個(gè)城市
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"})
#判斷請(qǐng)求的是文章詳情頁(yè)
elif response.meta["type"] == "article":
code = response.meta["code"]
htmlname = response.url.split("/")[-1].replace(r".html", "")
#提取出該文章中所有的圖片鏈接
images = response.xpath(
"http://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下載簡(jiǎn)單圖片或者文件的方法
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())
整體的爬蟲(chóng)代碼需要結(jié)合網(wǎng)頁(yè)的源碼看盅称,沒(méi)什么細(xì)節(jié)的就不多說(shuō)了,另外在工程目錄
的settings.py中,改下參數(shù)
# 設(shè)置為不遵守robot協(xié)議
#以及每次scrapy request 請(qǐng)求最小間隔為1s缩膝,防止被反爬蟲(chóng)
ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = 1
3.啟動(dòng)爬蟲(chóng)
爬蟲(chóng)啟動(dòng)很簡(jiǎn)單的混狠,cd 到 mafengwoscrapy工程目錄下執(zhí)行
scrapy crawl mafengwospider 即可
4.結(jié)果
爬取的速度不是很快,結(jié)果如截圖所示