四、通过CrawlSpider对招聘网站拉钩网进行整站爬取
使用CrawlSpider对于拉勾网进行整站爬取。
附带源码解读,数据库建表与爬取后将数据存入数据库等内容。
推荐工具cmder
http://cmder.net/
下载full版本,使我们在windows环境下也可以使用linux部分命令。
配置path环境变量
1. 设计拉勾网的数据表结构
2. 初始化拉钩网项目并解读crawl源码
scrapy genspider --list
查看可使用的初始化模板
ailable templates:
- basic
- crawl
- csvfeed
- xmlfeed
1 | scrapy genspider -t crawl lagou www.lagou.com |
cmd与pycharm不同,mark root
setting.py 设置目录
crawl模板
1 | class LagouSpider(CrawlSpider): |
源码阅读剖析
https://doc.scrapy.org/en/1.3/topics/spiders.html#crawlspider
提供了一些可以让我们进行简单的follow的规则,link,迭代爬取
rules:
规则,crawel spider读取并执行
parse_start_url(response):
example:
rules是一个可迭代对象,里面有Rule实例->LinkExtractor的分析allow=('category\.php', ), callback='parse_item',
allow允许的url模式。callback,要回调的函数名。
因为rules里面没有self,无法获取到方法。
1 | import scrapy |
分析拉勾网模板代码
- 将http加上s
- 重命名parse_item为我们自定义的parse_job
- 点击
class LagouSpider(CrawlSpider):
的CrawlSpider,进入crawl源码 class CrawlSpider(Spider):
可以看出它继承于spider- 入口:
def start_requests(self):
- alt+左右方向键,不同代码跳转
- 5->之后默认parse CrawlSpider里面有parse函数。但是这次我们不能向以前一样覆盖
Crawl.py核心函数parse。
parse函数调用_parse_response
1 | def parse(self, response): |
_parse_response
- 判断是否有callback即有没有self.parse_start_url
- 我们可以重载parse_start_url加入自己的处理
- 把参数传递给函数,并调用process_results函数
_parse_response函数
1 | def _parse_response(self, response, callback, cb_kwargs, follow=True): |
parse_start_url的return值将会被process_results方法接收处理
如果不重写,因为返回为空,然后就相当于什么都没做
1 | def process_results(self, response, results): |
点击followlink
1 | def set_crawler(self, crawler): |
如果setting中有这个参数,则可以进一步执行到parse
_requests_to_follow
- 判断传入的是不是response,如果不是直接returns
- 针对当前response设置一个空set,去重
- 把self的rules通过enumerate变成一个可迭代对象
- 跳转rules详情
- 拿到link通过link_extractor.extract_links抽取出具体的link
- 执行我们的process_links
- link制作完成发起Request,回调_response_downloaded函数
- 然后执行parse_respose
1 | def _requests_to_follow(self, response): |
_compile_rules
- 在我们初始化时会调用_compile_rules
copy.copy(r) for r in self.rules]
将我们的rules进行一个copy- 调用回调函数get_method。
- 调用rules里面我们定义的process_links
- 调用rules里面我们定义的process_request
1 | def _compile_rules(self): |
self.process_links = process_links
self.process_request = process_request
可以通过在rules里面传入我们自己的处理函数,实现对url的自定义。
达到负载均衡,多地不同ip访问。
_response_downloaded
通过rule取到具体的rule
调用我们自己的回调函数
1 | def _response_downloaded(self, response): |
- allow :符合这个url我就爬取
- deny : 符合这个url规则我就放弃
- allow_domin : 这个域名下的我才处理
- allow_domin : 这个域名下的我不处理
- restrict_xpaths:进一步限定xpath
1 | self, allow=(), deny=(), allow_domains=(), deny_domains=(), restrict_xpaths=(), |
extract_links
如果有restrict_xpaths,他会进行读取执行
1 | def extract_links(self, response): |
get_base_url:
urllib.parse.urljoin替我们拼接好url
1 | def get_base_url(text, baseurl='', encoding='utf-8'): |
编写rule规则
1 | rules = ( |
3. 设计lagou的items
需要用到的方法
1 | from w3lib.html import remove_tags |
定义好的item
1 | class LagouJobItem(scrapy.Item): |
重写的itemloader
设置默认只提取第一个
1 | class LagouJobItemLoader(ItemLoader): |
4. 提取字段值并存入数据库
1 | def parse_job(self, response): |
获得的拉勾网item数据
5. items中添加get_insert_sql实现存入数据库
1 | def get_insert_sql(self): |