首页 > Python编程 > python做爬虫的常见问题总结

python做爬虫的常见问题总结

2015年9月6日

python做爬虫的常见问题总结
http://blog.sina.cn/dpool/blog/s/blog_98cf2a6f01015h79.html?vt=4
从接触爬虫到现在也整整一年了,谈不上什么精通,只是摸爬滚打、吃一堑长一智,就算在泥潭里,多少也了解点怎样滚,才能少沾点泥巴。这一年里维护改进着日规模高峰达80w、均度50w的垂直爬虫系统,写过一些一次性抓取的小脚本,参与过破解接口、本地执行js进而获取抓取数据,调研过伪登录、利用cookie进行抓取,写过简单的价格图片识别脚本,维护着基于模板截图的c++ ocr图片识别服务,开发了用上redis的基于特征统计判重服务,进行过局部的死链检测优化……其实回过头来看,一年的时间我还是浪费了很多。这些东西或多或少跟抓取、搜索都有一些关系。临近年关,没那么忙的话,就理一理吧。
1、最基本的代码
import urllib2
content = urllib2.urlopen(‘http://XXXX’).read()
2、最基本的结构和流程
调度、下载、抽取、入库
3、可能遇到的问题
两个原则:1)下回来了没?没有的话想尽千方百计搞到本地2)下回来了,就要相信一定能提取出来,只是麻烦与否的问题
1)被封禁
A、adsl代理
import urllib2
proxy_support = urllib2.ProxyHandler({‘http’:’http://XX.XX.XX.XX:XXXX’})
opener = urllib2.build_opener(proxy_support, urllib2.HTTPHandler)
urllib2.install_opener(opener)
content = urllib2.urlopen(‘http://XXXX’).read()
其实以上几行代码是我从网上别处搞过来的,我一般小脚本那种一次性的抓取,用不上代理,而维护的垂直爬虫系统,下载那块主要借助的是pyqt4库,代理代码有一定耦合,就不在这里细说了,主要不是我自己写的,担心说不明白,那就不大好了,感兴趣的童鞋可以自己去研究pyqt4库,都是有很好支持的
B、控制对同一站点的访问频率(要是让它sleep、要么让它抓别的站点)
4、爬虫的自我伪装
对于需要登录的一般有以下几种处理方法:
1)直接模拟登录后的动作,利用cookie、携带用户信息等方式发起请求,绕过登录动作
2)机器人自动登录
3)直接使用webkit和js去操作登录
这里主要说一下前两种,不是因为对它们多熟,而是第三种我暂时压根没用过,⊙﹏⊙b汗
工具:firefox+httpfox
机器人自动登录:
这个东东其实原理很简单,就是程序post_data真实用户信息发起请求,至于最后能否成功登录获取登录后的信息,个人经验觉得跟对方校验严格程度有关,有些网站post_data有一些乱七八糟的数据值,你无法分析清楚,尽管携带真实用户信息请求,也总是返回用户名和密码不一致。而有的简单就容易攻破。
我实际工作中用的是直接模拟登录后访问的方法。大体代码如下:
import urllib,urllib2,cookielib
mycookie = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
openner = urllib2.build_opener(mycookie)
request = urllib2.Request(‘http:/*’)
request.add_header(‘Accept-Language’, ‘zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3’)
request.add_header(‘Connection’, ‘keep-alive’)
request.add_header(‘Accept-Encoding’, ‘gzip, deflate’)
request.add_header(‘X-Requested-With’, ‘XMLHttpRequest’)
request.add_header(‘Referer’, ‘http://****’)
cookie_str = ‘***’
request.add_header(‘Cookie’, cookie_str)
html_src = openner.open(request).read()
到这里基本已经完事,但你偶尔还会遇到一个问题:乱码
解决方法:
import gzip
from gzip import *
import os, io
import StringIO
html_data = GzipFile(fileobj=StringIO(html_src), mode=’r’).read()
5、多线程加速
其实这一块本身跟爬虫没多大关系了,对我这种菜鸟来讲,需要注意一点就是仔细理解线程,别把线程和函数调用混淆。建议使用线程池,至于具体代码,这个东东网上多去了,就不啰嗦了。
6、一些琐碎的东东
pyqt4本地模拟浏览器执行js
from PyQt4.QtWebKit import QWebPage, QWebElement
from PyQt4.QtCore import QCoreApplication, QThread, QUrl, SIGNAL, QTimer
app = QApplication(sys.argv)
downloader = QWebPage()
with open(‘***.js’) as f:
js = f.read()
js = js.replace(‘{{address}}’, encoded_lat_lng)
js_res_str = unicode(downloader.mainFrame().evaluateJavaScript(js).toString()
抽取失败怎么查?
1)检查下载回本地内容
是否下载完全?下载是否正确(即是否是自己想要的内容)?是否包含所要抽的内容?
有时由于网络原因,它会下载不全;有时由于封禁等会导致下载非所要内容,甚至会被通知“机器人检查”;有时由于js加载等浏览器本地处理,导致你在页面能看到,并不代表你就已经下载回所看到的内容了。其实web是这样的,网页文本是一部分,会随着当次请求返回,而其余的类似css\js\图片等等,第一次获取到的只是url等信息,也就是说我们从浏览器看到的一次请求实际上是包含了n次请求的,或前或后最后统一由浏览器加载呈现。
2)检查xpath是否正确
当然也可以是其他的定位方法,这里拿xpath举例。xpath是否准确定位到所需信息?
3)检查提取方法是否正确
可以用正则,也可以用python自带的字符串处理函数,这个看你喜欢,但貌似正则看起来更美观些。期间我遇到情况有:信息藏在利用工具获取的xpath节点的父节点、信息做了简单防抓取截断甚至js等处理……这些情况可以仔细分析网页源码加以针对解决,再唠叨一句,记住——只要到了本地,那就是你的天下,有就一定能抽出来。
4)图片抽取失败呢?
首先看是否进行了全局抽取,有的为了防止抓到广告图片,限定了抽取范围,而一旦对方变了模板,此时的图片抽取会失效。其次就是程序逻辑了,是否进行了次数限制,比如前边弄了5张,就不去扫描下面的内容了。
除了封禁,对方还会采取哪些常见的信息保护措施?
1)信息图片化
这样即使你抓到该图片,要想获取信息,也得费一番劲了。常见的比如价格图片、电话图片、验证码等等。而作为抓取方,这就得依赖后端服务了,比如图片识别ocr,这个就不在这里说了。
2)有意信息截断分开存储
拿电话图片举例,我遇到过前三位存一个地方,后八位显示星号,用户通过点击button获取完整的电话号码,其实这纯粹是个防傻瓜机器人的trick,你要想复杂的做可以模拟js点击,再获取。但更简单的方法是分析其网页源码,找到分散的部分,直接正则分别提取,再拼接即可。
3)对非登录用户不展示
这个的话,其实我现在没有什么太好的办法。临时抓取可以利用上面的破解登录的方法,但长期来看的话,别人想kill掉你是很容易的,因为你短时间内同一账号大规模的访问这个是极其容易被发现的,除非对方弱智或者压根不想管你。不然就是你有成千上万个马甲,你要搞到这种程度,我也只能拜服了。应个景,12306要想封插件个人觉得技术肯定不是问题,很简单啊,你一个账号10、20分钟五秒钟刷一次,避免误判,我忍了,可你连续几小时这样,我立马就给你封了。O(∩_∩)O哈哈~,其实他是不想真那么干罢了。
……
本篇的话感觉主要关注一些比较细节方面的东西即可,至于爬虫系统的方面东东再起一篇吧
系统架构(从种子到模板到入库到死链检查整个一套机制如何运转)
调度、如何让其平稳长时间运行(包括出去了回不来、出不去、新比例)站点如何做到平衡
downloader主要是多进程、异步转同步、pyqt webkit渲染
抽取的模板机制,如何保证关系不混乱、列表页、详情页、抽取field
入库就没什么太多可讲的了
引擎是怎么统领全局的
……

分类: Python编程 标签:
本文的评论功能被关闭了.