简介
scrapy爬虫这个东西我就不多做介绍了,总之是一个很好用的Python爬虫库,且关于scrapy也有较多的教程。这篇文章记录一下我个人的项目规划和天坑心得。
通常来说,我们执行了scrapy startproject example
后就会创建这样的一个文件结构,大致如下:
├── example
│ ├── __init__.py
│ ├── __pycache__
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
│ ├── __init__.py
│ └── __pycache__
└── scrapy.cfg
我们通常写爬虫都是在spiders里写爬虫解析规则,以及编写数据存储程序。
基础spider
我们首先来看爬虫程序,最基本是以下这个样子:
import scrapy
from sqlalchemy import distinct
class ExampleSpider(scrapy.Spider):
name = 'example_spider'
allowed_domains = []
start_urls = [
'https://www.example.com'
]
def parse(self,response):
pass
这样的一个基本爬虫,只要配置好start_urls,在这里写上我们想要去爬的URL,可以编写很多个,start_urls是一个数组。然后执行scrapy crawl example_spider
就会自动去爬数据了。这里的parse
方法是继承父类scrapy.Spider的解析方法,此处没有做任何结果解析以及存储。
在这个地方,其实我们要注意一点是,ExampleSpider这个类名我们可以瞎姬霸命名,我们在调用scrapy crawl [爬虫名]
的时候,这个爬虫名是根据这个类里的name
属性来的,此处的name
为example_spider
,所以我们在执行的时候就是:scrapy crawl example_spider
。当然在具体的编写过程中我个人建议是不要瞎姬霸命名,按照业务逻辑来。
再回头看我上面所展示的文件夹结构,随着业务的增长,我们很可能编写个成百上千的爬虫,那么每个爬虫都放到spiders
一个文件夹里的话,要理清的话就要花大力气了,而实际上,在spiders
其实可以创建任意的子文件夹进行逻辑上的分类,执行crawl
的时候,会自动去遍历路径找到我们制定的爬虫,至于你编写了哪些爬虫,同样可以通过crapy list
列出来。
分页爬技巧
分页爬虫技巧,其实在搜索引擎上都能找到,而且在segmentfault上都能搜到相应的解答,主要就在parse
方法中判断条件或者说找到下一页的URL,然后用协程yield
一下scrapy.Request
就可以了,也就是用协程方式手动执行一下scrapy的Request
方法,对于Request具体的返回,我没有深入看源代码研究,大概是在scrapy的底层再次做了一定的处理,实际的请求并不是Request
类发起的。
常用配置
这里要结合一些原因来进行说明。
- 通常来说,移动端的数据更好爬,我们可以用chrome的开发者工具模拟移动端浏览器,然后看移动端的数据交互形式以及移动端HTML数据格式。
- 另外就是我们爬的时候通常为了防止被封IP,不能太频繁,一般是间隔1s钟去取一次数据这样子。
所以从上面两方面来说,我们在自己写的爬虫类中加上一个类属性download_delay
,如
import scrapy
from sqlalchemy import distinct
class ExampleSpider(scrapy.Spider):
download_delay = 1 # 1s钟发起一次请求,当前爬虫执行过程中,对任何位置的Reqeust都有效
name = 'example_spider'
allowed_domains = []
start_urls = [
'https://www.example.com'
]
def parse(self,response):
pass
另外就是在settings.py
设置
DEFAULT_REQUEST_HEADERS = {
'user-agent' : 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3423.2 Mobile Safari/537.36'
}
一个这样的header头,模拟手机浏览器。
错入日志的重要性
在做爬虫的时候,非常重要的一点就是错误日志的记录,通常来说我们在settings.py
中配置以下两个参数:
LOG_LEVEL = 'DEBUG'
LOG_FILE = './log.log' # 错误日志记录文件及路径
通常来说,我们最好是把LOG_LEVEL
设置为DEBUG
,也就是说,我们把所有的调试信息都输入到错误日志中进行记录,方便检查编写爬虫过程中可能出现的任何问题,尽可能的确保每个环节不出错。
如果没有意识到错误日志的重要性,在写爬虫的过程中只能抓瞎了,我是踩了好几次大坑才有过这种觉悟。
数据存储
数据存储,我个人用的是sqlalchemy
,是一个很强大的库,我个人也做了些基础的封装,使用起来更方便。
数据存储一方面可能是在parse
方法中进行解析后处理,另外的话,parse可以进行统一解析,然后在close
进行全部批量存储,主要看具体的业务逻辑情况。
遇到过最坑爹的问题
最坑爹的问题就是要千万保证数据来源性的可靠,一定要反复对比其来源数据是否有问题,不然出现我们所医疗之外的数据情况,很可能找不到原因。
举个例子,我们在做分页处理的时候,已经到末尾页了,通常就可以判定结束爬虫了,但假设在某一个数据分类下,这个末尾页其实有个链接指向了其他分类页,然而在web浏览器中通过javascript
程序禁止了跳转,然后就陷入了不断循环的取数据的过程中或者重复取了数据。当然这个是一个不太可能存在的可能情况,不过我在编写的过程中就遇到过类似的问题,在处理的时候千万要保证数据解析和来源数据的可靠性,切记切记!