1.项目搭建
1、scrapy startproject Lianjia
2、cd Lianjia
3、scrapy genspider lianjia www.lianjia.com #爬虫程序名和目标域名
4、items.py
#定义要爬取的数据结构
class LianjiaItem(scrapy.Item):
name = scrapy.Field()
price = scrapy.Field()
5、lianjia.py
import scrapy
class LianjiaSpider(scrapy.Spider):
name = ‘lianjia’ #爬虫名称
allowed_domains = [‘www.lianjia.com’] #允许爬取的域名
start_urls = [‘自己写一个第1页地址’]
#定义页面解析函数
def parse(self,response):
pass
6、pipelines.py
class LianjiaPipeline(object):
def process_item(self,item,spider):
pass
7、修改配置:settings.py
1、ROBOTSTXT_OBEY = False
2、USER_AGENT = ‘’
3、DEFAULT_REQUEST_HEADERS = {}
4、ITEM_PIPELINES = {
‘Lianjia.pipelines.LianjiaPipeline’ : 200,
}
8、cmd启动项目:scrapy crawl lianjia
9、pycharm运行爬虫项目
创建begin.py(和scrapy.cfg文件同目录)
begin.py
from scrapy import cmdline
cmdline.execute(‘scrapy crawl baidu’.split())
2.项目结构
scrapy框架 :异步处理框架
1、组成
引擎(Engine)
调度器(Scheduler)
下载器(Downloader)
爬虫程序(Spider)
项目管道(Item Pipeline)
下载器中间件(Downloader Middlewares)
蜘蛛中间件(Spider Middlewares)
2、流程
1、Engine向Spider索要第一个要爬取的URL
2、交给Scheduler入队列
3、出队列,通过Downloader Middlewares给下载器
4、下载完成后,通过Spider Middlewares给Spider
5、Spider数据提取:
1、数据交给Item Pipeline
2、需要继续跟进URL,交给Scheduler入队列
3.补充知识点
1、extract() :获取选择器对象中的文本内容,scrapy中xpath提取出的是选择器对象的列表
response.xpath(’’)
结果 :[<selector … data=‘文本内容’>,<…>]
response.xpath(’’).extract()
结果 :[‘文本内容1’,‘文本内容2’,…]
2、pipelines.py中必须有1个函数叫:
def process_item(self,item,spider):
# 必须返回item,其他管道才能继续使用
return item
# 爬取结束后的善后操作,如关闭mysql的油表和数据库对象
def close_spider(self,spider):
…
3、日志级别
LOG_LEVEL = ‘WARNING’ # 过滤掉warning以下的信息
LOG_FILE = ‘文件名.log’ # 设置日志文件后,日志信息会写入日志文件,不会输出到终端
5层日志级别
1、CRITICAL :严重错误
2、ERROR :一般错误
3、WARNING :警告信息(只显示WARNING、ERROR、CRITICAL信息)
4、INFO :一般信息
5、DEBUG :调试信息
4、保存为csv、json文件(begin.py中的cmd指令)
1、json文件
scrapy crawl daomu -o daomu.json
设置导出编码: settings.py添加变量
FEED_EXPORT_ENCODING = ‘gb18030’
2、csv文件
scrapy crawl daomu -o daomu.csv
csv文件出现空行解决方法(修改源码)
C:\Users\Python\Anaconda3\Lib\site-packages\scrapy\exporters.py 做如下修改(搜索csv类):
self.stream = io.TextIOWrapper(
file,
newline=’’, # 添加此行
4.下载器中间件
项目目录中新建useragents.py和proxies.py存放大量User-Agent和代理ip
ualist = [
'Mozilla/5.0', 'UA1', 'UA2', 'UA3', 'UA4',
]
proxy_list = [
'http://127.0.0.1:8888',
'http://127.0.0.1:8888',
]
middlewares.py中新建中间件类
from scrapy import signals
from .useragents import ualist
import random
from .proxies import proxy_list
# 随机生成user-agent下载器中间件
# url出队列,交给下载器下载前会经过中间件
# 此处在下载前设置了request中的参数
# 写完后要去settings中开启下载器中间件
class RandomUAMiddleware(object):
def process_request(self,request,spider):
request.headers['User-Agent'] = random.choice(ualist)
print(random.choice(ualist))
# 随机使用代理下载器中间件
class RandomProxyMiddleware(object):
def process_request(self,request,spider):
request.meta['proxy'] = random.choice(proxy_list)
print(random.choice(proxy_list))
settings.py中开启下载器中间件
# 开启下载器中间件,数字越小,优先级越高
DOWNLOADER_MIDDLEWARES = {
'Tmiddle.middlewares.TmiddleDownloaderMiddleware': 543,
'Tmiddle.middlewares.RandomUAMiddleware': 200,
'Tmiddle.middlewares.RandomProxyMiddleware': 100,
}
5.scrapy shell使用(类似ipython)
1、终端输入:scrapy shell URL地址
*2、request.headers :请求头(字典)
*3、request.meta :定义代理等相关信息(字典)
4、response.text :响应字符串
5、response.body :响应字节流
6、response.xpath(’’)
6、scrapy.Request()常用参数:yield给调度器的方法
1、url
2、callback
3、headers 这个会在settings或中间件中设置,一般不写
*4、meta :定义代理等相关信息{‘proxy’:’’}
代理一般写在中间件中(不然那么多url只用一个代理,岂不是太坑)
*5、dont_filter :是否忽略域组限制
默认为False,检查allowed_domains=[’’]