首先呢,命令行切换目录到桌面建立一个新scrapy项目
(不要问qwer是什么,起名就是这么随意)
>cd desktop
>scrapy startproject qwer
简述一下大致整个过程:
首先输入scrapy crawl qwer启动爬虫文件,
然后爬虫文件会发送start_urls里的请求,会获取相应response,
接着response会传到parse函数中进行处理提取所需数据,
之后提取的数据会存到item对象里,item对象通过yield返回到管道文件,
最后管道进行处理并储存每个item对象,处理完后返回item,并准备接受下一个
第一步:定义items文件
import scrapy
class QwerItem(scrapy.Item): #按照格式来就行
# name = scrapy.Field()
产地 = scrapy.Field()
类型 = scrapy.Field()
评分 = scrapy.Field()
名字 = scrapy.Field()
评分人数 = scrapy.Field()
…………
第二步:爬虫主程序
在spiders文件夹下新建一个.py文件,这些是我导入的库
import scrapy
import json
import requests
import re
from qwer.items import QwerItem
定义出 爬虫的类
class QwerSpider(scrapy.Spider):
#先初始化
name = 'qwer'
###可选allowed_domains = ['douban.com']
#起始页面用的是我不是药神
start_urls = ['https://movie.douban.com/subject/26752088/']
#这段代码产出第一部电影的详细信息
def parse(self,response):
sites = response.xpath('//div[@id="content"]')
for i in sites:
#创建item对象,用来储存数据
item = QwerItem()
item['名字'] = i.xpath('h1/span[1]/text()').extract()
item['类型'] = i.xpath('//*[@id="info"]/span[@property="v:genre"]/text()').extract()
………………
#返回给管道文件处理 然后回来继续下个循环
yield item
在正常爬取数据时发现有些信息发现有些信息如产地,语言,无法精确定位。所以我的思路是,先用text()爬取上一级目录下所有无法精确定位的内容(即引号内数据),然后通过正则表达式找出所需信息
#这段代码读取产地等信息
chan_di = i.xpath('//*[@id="info"]/text()').extract()
x = re.compile(r'[u4e00-u9fa5]') #引入正则表达式搜寻汉字
for k in range(len(chan_di)):
data = re.findall(x, chan_di[k])
if data: #只要找到第一组汉字就退出
y = chan_di[k] #因为取得的第一组汉字就是产地
break
item['产地']= y #写入产地信息
翻页程序,因为豆瓣采用的动态加载翻页的,所以需要先进入网页开发模式,在Network下面选择XHR,然后刷新页面,如图所示的URL就是其正在的地址,每次点击“加载更多”后都会产生一个新地址,与第一个相比,只有start=后面的数字是变化的,按照每页20部电影的速度变化着
写一段for循环,循环次数可以自定义(看你想爬多少电影了)
然后这里我是通过python的requests库得到每个页面上20部电影的详细地址
#接在parse函数下面,这段代码产出每一部电影的具体网址
for m in range(500):
url_0 = 'https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={}'.format(m*20)
#这里返回的是 json文件所以要用 .json()
datas = requests.get(url_0).json()
dict_0 = datas['data'] #datas是一个字典,里面的data键里包含了所需要的全部信息
for n in dict_0[1:]: #去掉上面已经爬取的我不是药神
z = n['url'] #读取每个页面上的每一部电影的网址
zz = z.replace('','') #读取出的原始网址中包含许多反斜杠,去掉
yield scrapy.Request(zz,callback = self.parse_next) #打开每一部电影的网址爬取信息
然后为了不进行无限循环,再重新定义一个parse_next函数(和原parse相同)来产出数据
#这段代码产出每部电影的相关信息
def parse_next(self,response):
…………
yield item
#代码与上面parse函数相同,不过到yield item 就结束,不再需要下面的for循环
第三步定义管道文件
负责来处理item字段,最后储存成json文件
class QwerPipeline(object):
def __init__(self):
self.f = open('dianyssing_shuju.json',"w") #打开一个json文件
def process_item(self, item, spider):
#要先把item转行成字典,其中ascii设置为否则中文可以按Unicode处理
content = json.dumps(dict(item),ensure_ascii = False)+",n" #返回的是字符串,输出完一部后换行
self.f.write(content) #写入
return item #表明这条item数据处理完了
def close_spider(self,spider):
self.f.close() #关闭文件
其中如果在json.dumps时发现字典里面有bytes类型的数据,无法编码,则可以在管道文件中自定义一个继承json.JSONEncoder的子类。然后在json.dumps时加入参数cls=Myencoder
class Myencoder(json.JSONEncoder): #继承json.JSONEncoder的一个子类
def default(self, obj):
if isinstance(obj, bytes): #把bytes类型的数据转化成str类型
return str(obj, encoding='utf-8')
return json.JSONEncoder.default(self, obj)
定义完管道文件就要在settings文件里启动它
第四步设置settings文件
先启动一下管道文件,启用管道文件优先级 0-1000,值越小,优先级越高,可以指定多个管道文件,item会依次经过它们
ITEM_PIPELINES = {
'qwer.pipelines.QwerPipeline': 300,
}
然后可以设置一些反爬虫措施:
1.设置爬取间隔时间(也是最简单的方法)
DOWNLOAD_DELAY = 3
2.设置随机User Agent
先在settings下写入,建一个UA池
USER_AGENTS = [
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
……………
]
然后在middlewares文件中自定义一个类,这个类继承自UserAgentMiddleware。其中scrapy已经提供了from_crawler()的方法,用来访问设置信息
import scrapy
from scrapy import signals
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
import random
class MyUserAgentMiddleware(UserAgentMiddleware):
def __init__(self, user_agent):
self.user_agent = user_agent
@classmethod
def from_crawler(cls, crawler):
return cls(
user_agent=crawler.settings.get('USER_AGENTS') #从settings中读取UA
)
def process_request(self, request, spider):
agent = random.choice(self.user_agent) #随机选择一个UA
print("当前的UA为: " + agent) #看看选了哪个
request.headers['User-Agent'] = agent #添加到headers里面
最后把刚刚定义的类添加到settings的DOWNLOADER_MIDDLEWARES里面
DOWNLOADER_MIDDLEWARES = {
#'qwer.middlewares.QwerDownloaderMiddleware': 543,
'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None,
'qwer.middlewares.MyUserAgentMiddleware': 400
}
Done~!
3.使用代理ip
首先也是在settings里面添加ip池(免费的ip基本都不行,需要自行购买ip)
Ips=[
{"http://61.129.70.131:8080"},
{"http://61.152.81.193:9100"},
{"http://120.204.85.29:3128"},
{"http://219.228.126.86:8123"},
{"http://61.152.81.193:9100"},
{"http://218.82.33.225:53853"},
……
]
同样的
import scrapy
from scrapy import signals
import random
class ProxyMiddleware(object):
def __init__(self, ip):
self.ip = ip
@classmethod
def from_crawler(cls, crawler):
return cls(ip=crawler.settings.get('Ips'))
def process_request(self, request, spider):
ip = random.choice(self.ip)
request.meta['proxy'] = ip
添加到settings的DOWNLOADER_MIDDLEWARES里面
DOWNLOADER_MIDDLEWARES = {
……
'qwer.middlewares.ProxyMiddleware': 543
}
Done~!
终于搞完了,先放个自拍压压惊
----------------------分割线-------------------------
最后得到的json文件如图
然后导入到Excel文件中
之后就可以进行数据分析啦~!
寻找了一下传说中的高分冷门电影
df[(df.投票人数>100)&(df.投票人数8.0)&(df.年代>2000)&(df.时长>85)&(df.类型.str.contains('喜剧'))]
- 我的微信
- 微信扫一扫
-
- 我的微信公众号
- 微信扫一扫
-
评论