快一年没更新博客了,现在总结一下这大半年来研究、学习的知识。
这个爬虫项目是去年 4、5 月份做的,主要技术是 BeautifulSoup、select、requests、MongoDB、highchart
首先,我们登陆赶集网可以看到二手商品信息的首页,即爬虫的起始 url 是:,分析网页结构可以看到二手商品信息分类中有:手机、手机配件、手机号码、笔记本电脑、台式机等 20 多个商品分类子频道,分别打开每个子频道的 url,可以看到对应的二手商品列表,每个二手商品列表中的 url 对应一个详细页面,我们要获取的就是每个详细页面上的信息。
首先,我们定义 headers 部分,headers 包含 User-Agent、Cookie、Referer 等信息,这是为了伪装成浏览器的形式,以应对反爬虫措施。
requests.get 解析 url:
- wb_data = requests.get(url, headers=headers)
BeautifulSoup 的 lxml 解析文本:
- soup = BeautifulSoup(wb_data.text, 'lxml')
关于 BeautifulSoup 中的各种 html 解析器,我做了一个小的研究,html.parser:这是 python 自带的,速度上当然是没问题的,但是兼容性不好, python2.7.3 以前的版本不兼容;lxml:解析速度很快、兼容性好,但是正因为其解析速度快,有时会出现解析不到数据的情况;html5lib:兼容性非常好,解析成功率非常高 (有时用 lxml 解析不到时,用 html5lib 却能解析到),但是速度非常慢;综合这三种 html 解析器,我觉得 lxml 是最为折中的。
select 选择器定位文本:
- links = soup.select('div.main-pop dl dt a')
获取详细信息:
- data = {
- 'title': soup.title.text.strip(),
- 'price': soup.select('i.f22.fc-orange.f-type')[0].text,
- 'area': list(map(lambda x: x.text.strip(), soup.select('ul.det-infor li:nth-of-type(3) a')[1:])),
- 'fdate': soup.select('i.pr-5')[0].text.strip()[:-3],
- 'cates': list(map(lambda x: x.text, soup.select('div.crumbs.routes.clearfix a'))),
- 'url': url
- }
把详细信息存储到字典 data 中,然后将 data 插入到 mongodb 数据库中
断点续传去重:
在持续爬取的过程中,往往会遇到网络中断、ip 被封、断电等等的情况,为确保在网络恢复正常时爬虫能够继续生效,引入断点续传:
- db_urls = [item['url'] for item in ganji_url_list.find()]
- index_urls = [item['url'] for item in ganji_info.find()]
- x = set(db_urls)
- y = set(index_urls)
- rest_of_urls = x - y
由于我们是根据每个 url 爬取其详细信息的,首先把 url 爬取到数据库中,然后从数据库中查找详细信息中的 url(已经爬取的),与总的 url 做差,得到未爬取的 url,当前从未爬取的 url 开始,这样可以保证爬取的信息不会是重复的
最后,总结下爬取赶集网遇到的反爬措施:
1、直接暴力爬取 (很多网页解析不到数据)
2、伪装成浏览器进行爬取,并设置延时 (爬一段时间后发现 IP 被封)
3、伪装成浏览器、使用随机代理 IP、设置随机延时 (爬几天之后发现会弹出输入验证码的对话框),但是它的反爬措施仍不够完善,当出现验证码时,反复地多请求几次,验证码就不会出现了
爬虫部分代码详见 github:
来源: