爬虫代码阅读-登陆,广度遍历与深度遍历
代码地址: https://github.com/WiseDoge/Spider_Hub/tree/master/ZhiHu
之前一直不太了解分布式爬虫设计思路,于是在github上搜了一个简易的分布式爬虫,学习了一下实现思路,并做一下对应笔记
分布式爬虫主要涉及到三个方面。
1.模拟登录;
2.master广度遍历,将待爬页push到队列(redis);
3.slave从redis中取出待爬页,进行深度遍历
下面分三个方面分别阐述,以知乎为例。
一.模拟登录
1.首先可以自己手动登陆一次,注意登陆时post的数据以及url
这里post数据格式为:
postdata = { '_xsrf': get_xsrf(session), 'password': secret, 'remember_me': 'true', 'email': account, }
其中_xsrf这个字段,在登陆页的源码中可以找到这个字段,但它是一个动态变化的参数,因此必须保证在得到字段值后在同一个session中去做登陆操作。另外可以做的额外操作是将cookie本地化,
然后以后去请求时,从本地加载cookie,如果登陆失败,再重新去做登陆操作。另一个就是验证码的识别,可以用pytesseract来做自动识别(记得安装pytesseract外,装上tesseract ocr,因为
pytesseract只是一个wrapper),今天经过尝试发现其实它的识别率很低,在这里采用的方式是image.show,然后人工识别。看了好几个版本的知乎登陆源码,发现基本上用的都是类似的方式,
另外,目前知乎全站已用https,直接使用之前的源码,可能会返回403.
二.Master设计
登陆结束后,就能正式开始进行爬虫操作了。
这里的广度遍历比较精简,就是一个递归,怎么做的呢
1.获取入口页的关注者列表,
2.然后随机获取并剔除一条数据,作为下一次抓取的入口,push到队列。此处redis主要就是起到队列的作用
3.不断递归
核心代码如下:
def crawl(url): followees = get_followees(url) one = get_next_url(followees) try: test_list = get_followees(one) put_into_queue(followees) print(one) crawl(one) except NoFolloweeError: next_random_url = conn.srandmember("UrlSet", 1)[0].decode("utf-8") crawl(next_random_url)
三.Slave设计
假设有一些代理主机,在这里,一台主机开启一个线程,每一个线程去打开一个网页,解析网页后,将有用信息存储到mongodb,为什么用mongodb,这是因为mongodb比mysql更适合用于分布式存储。
slave设计应该是比较灵活的,可以根据自己的设备条件来做调整。不过源码有应该还是有一些问题的。
1.队列取出url后没看到有剔除操作;
2.代理是新启用一个session,所以可能会遇到无法登陆的情况,这个可以将登陆后的cookie本地化后,在代理主机中加载cookie即可解决。