网络爬虫程序的爬虫的设计中应该注意的问题
不要盗取别人网站中的信息.
注意别人的爬取规则.
不要重复爬取.
不要影响人家的服务器.
只要是机器,比人快,效能就是最好的原则.
注意爬取信息的对象与集磊分类,便可以更准确的获取有用的信息.
就目前而言,好似没有会遵守规则的爬取者.
给你一个例子,可以看看:
import requests
import time
import json
import os
import re
import sys
import subprocess
from bs4 import BeautifulSoup as BS
class ZhiHuClient(object):
"""连接知乎的工具类,维护一个Session
2015.11.11
用法:
client = ZhiHuClient()
# 第一次使用时需要调用此方法登录一次,生成cookie文件
# 以后可以跳过这一步
client.login("username", "password")
# 用这个session进行其他网络操作,详见requests库
session = client.getSession()
"""
# 网址参数是账号类型
TYPE_PHONE_NUM = "phone_num"
TYPE_EMAIL = "email"
loginURL = r"http://www.zhihu.com/login/{0}"
homeURL = r"http://www.zhihu.com"
captchaURL = r"http://www.zhihu.com/captcha.gif"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xmlq=0.9,image/webp,*/*q=0.8",
"Accept-Encoding": "gzip, deflate",
"Host": "www.zhihu.com",
"Upgrade-Insecure-Requests": "1",
}
captchaFile = os.path.join(sys.path[0], "captcha.gif")
cookieFile = os.path.join(sys.path[0], "cookie")
def __init__(self):
os.chdir(sys.path[0]) # 设置脚本所在目录为当前工作目录
self.__session = requests.Session()
self.__session.headers = self.headers # 用self调用类变量是防止将来类改名
# 若已经有 cookie 则直接登录
self.__cookie = self.__loadCookie()
if self.__cookie:
print("检测到cookie文件,直接使用cookie登录")
self.__session.cookies.update(self.__cookie)
soup = BS(self.open(r"http://www.zhihu.com/").text, "html.parser")
print("已登陆账号: %s" % soup.find("span", class_="name").getText())
else:
print("没有找到cookie文件,请调用login方法登录一次!")
# 登录
def login(self, username, password):
"""
验证码错误返回:
{'errcode': 1991829, 'r': 1, 'data': {'captcha': '请提交正确的验证码 :('}, 'msg': '请提交正确的验证码 :('}
登录成功返回:
{'r': 0, 'msg': '登陆成功'}
"""
self.__username = username
self.__password = password
self.__loginURL = self.loginURL.format(self.__getUsernameType())
# 随便开个网页,获取登陆所需的_xsrf
html = self.open(self.homeURL).text
soup = BS(html, "html.parser")
_xsrf = soup.find("input", {"name": "_xsrf"})["value"]
# 下载验证码图片
while True:
captcha = self.open(self.captchaURL).content
with open(self.captchaFile, "wb") as output:
output.write(captcha)
# 人眼识别
print("=" * 50)
print("已打开验证码图片,请识别!")
subprocess.call(self.captchaFile, shell=True)
captcha = input("请输入验证码:")
os.remove(self.captchaFile)
# 发送POST请求
data = {
"_xsrf": _xsrf,
"password": self.__password,
"remember_me": "true",
self.__getUsernameType(): self.__username,
"captcha": captcha
}
res = self.__session.post(self.__loginURL, data=data)
print("=" * 50)
# print(res.text) # 输出脚本信息,调试用
if res.json()["r"] == 0:
print("登录成功")
self.__saveCookie()
break
else:
print("登录失败")
print("错误信息 --->", res.json()["msg"])
def __getUsernameType(self):
"""判断用户名类型
经测试,网页的判断规则是纯数字为phone_num,其他为email
"""
if self.__username.isdigit():
return self.TYPE_PHONE_NUM
return self.TYPE_EMAIL
def __saveCookie(self):
"""cookies 序列化到文件
即把dict对象转化成字符串保存
"""
with open(self.cookieFile, "w") as output:
cookies = self.__session.cookies.get_dict()
json.dump(cookies, output)
print("=" * 50)
print("已在同目录下生成cookie文件:", self.cookieFile)
def __loadCookie(self):
"""读取cookie文件,返回反序列化后的dict对象,没有则返回None"""
if os.path.exists(self.cookieFile):
print("=" * 50)
with open(self.cookieFile, "r") as f:
cookie = json.load(f)
return cookie
return None
def open(self, url, delay=0, timeout=10):
"""打开网页,返回Response对象"""
if delay:
time.sleep(delay)
return self.__session.get(url, timeout=timeout)
def getSession(self):
return self.__session
if __name__ == '__main__':
client = ZhiHuClient()
# 第一次使用时需要调用此方法登录一次,生成cookie文件
# 以后可以跳过这一步
# client.login("username", "password")
# 用这个session进行其他网络操作,详见requests库
session = client.getSession()
?2、Web爬虫是一种自动访问网页的脚本或机器人,其作用是从网页抓取原始数据 - 最终用户在屏幕上看到的各种元素(字符、图片)。 其工作就像是在网页上进行ctrl + a(全选内容),ctrl + c(复制内容),ctrl + v(粘贴内容)按钮的机器人(当然实质上不是那么简单)。
首先爬虫框架有三种
分布式爬虫:Nutch
JAVA单机爬虫:Crawler4j,WebMagic,WebCollector
非JAVA单机爬虫:scrapy
第一类:分布式爬虫 优点:海量URL管理
网速快
缺点:Nutch是为搜索引擎设计的爬虫,大多数用户是需要一个做精准数据爬取(精抽取)的爬虫。Nutch运行的一套流程里,有三分之二是为了搜索引擎而设计的。对精抽取没有太大的意义。
用Nutch做数据抽取,会浪费很多的时间在不必要的计算上。而且如果你试图通过对Nutch进行二次开发,来使得它适用于精抽取的业务,基本上就要破坏Nutch的框架,把Nutch改的面目全非。
Nutch依赖hadoop运行,hadoop本身会消耗很多的时间。如果集群机器数量较少,爬取速度反而不如单机爬虫。
Nutch虽然有一套插件机制,而且作为亮点宣传。可以看到一些开源的Nutch插件,提供精抽取的功能。但是开发过Nutch插件的人都知道,Nutch的插件系统有多蹩脚。利用反射的机制来加载和调用插件,使得程序的编写和调试都变得异常困难,更别说在上面开发一套复杂的精抽取系统了。
Nutch并没有为精抽取提供相应的插件挂载点。Nutch的插件有只有五六个挂载点,而这五六个挂载点都是为了搜索引擎服务的,并没有为精抽取提供挂载点。大多数Nutch的精抽取插件,都是挂载在“页面解析”(parser)这个挂载点的,这个挂载点其实是为了解析链接(为后续爬取提供URL),以及为搜索引擎提供一些易抽取的网页信息(网页的meta信息、text)
用Nutch进行爬虫的二次开发,爬虫的编写和调试所需的时间,往往是单机爬虫所需的十倍时间不止。了解Nutch源码的学习成本很高,何况是要让一个团队的人都读懂Nutch源码。调试过程中会出现除程序本身之外的各种问题(hadoop的问题、hbase的问题)。
Nutch2的版本目前并不适合开发。官方现在稳定的Nutch版本是nutch2.2.1,但是这个版本绑定了gora-0.3。Nutch2.3之前、Nutch2.2.1之后的一个版本,这个版本在官方的SVN中不断更新。而且非常不稳定(一直在修改)。
第二类:JAVA单机爬虫 优点:支持多线程。
支持代理。
能过滤重复URL的。
负责遍历网站和下载页面。爬js生成的信息和网页信息抽取模块有关,往往需要通过模拟浏览器(htmlunit,selenium)来完成。
缺点: 设计模式对软件开发没有指导性作用。用设计模式来设计爬虫,只会使得爬虫的设计更加臃肿。 第三类:非JAVA单机爬虫 优点:先说python爬虫,python可以用30行代码,完成JAVA
50行代码干的任务。python写代码的确快,但是在调试代码的阶段,python代码的调试往往会耗费远远多于编码阶段省下的时间。
使用python开发,要保证程序的正确性和稳定性,就需要写更多的测试模块。当然如果爬取规模不大、爬取业务不复杂,使用scrapy这种爬虫也是蛮不错的,可以轻松完成爬取任务。
缺点:bug较多,不稳定。
爬虫可以爬取ajax信息么?网页上有一些异步加载的数据,爬取这些数据有两种方法:使用模拟浏览器(问题1中描述过了),或者分析ajax的http请求,自己生成ajax请求的url,获取返回的数据。如果是自己生成ajax请求,使用开源爬虫的意义在哪里?其实是要用开源爬虫的线程池和URL管理功能(比如断点爬取)。
如果我已经可以生成我所需要的ajax请求(列表),如何用这些爬虫来对这些请求进行爬取?爬虫往往都是设计成广度遍历或者深度遍历的模式,去遍历静态或者动态页面。爬取ajax信息属于deepweb(深网)的范畴,虽然大多数爬虫都不直接支持。但是也可以通过一些方法来完成。比如WebCollector使用广度遍历来遍历网站。爬虫的第一轮爬取就是爬取种子集合(seeds)中的所有url。简单来说,就是将生成的ajax请求作为种子,放入爬虫。用爬虫对这些种子,进行深度为1的广度遍历(默认就是广度遍历)。
爬虫怎么爬取要登陆的网站?这些开源爬虫都支持在爬取时指定cookies,模拟登陆主要是靠cookies。至于cookies怎么获取,不是爬虫管的事情。你可以手动获取、用http请求模拟登陆或者用模拟浏览器自动登陆获取cookie。
爬虫怎么抽取网页的信息?开源爬虫一般都会集成网页抽取工具。主要支持两种规范:CSSSELECTOR和XPATH。
网页可以调用爬虫么?爬虫的调用是在Web的服务端调用的,平时怎么用就怎么用,这些爬虫都可以使用。
爬虫速度怎么样?单机开源爬虫的速度,基本都可以讲本机的网速用到极限。爬虫的速度慢,往往是因为用户把线程数开少了、网速慢,或者在数据持久化时,和数据库的交互速度慢。而这些东西,往往都是用户的机器和二次开发的代码决定的。这些开源爬虫的速度,都很可以。
1.带cookielib和urllib2
import urllib2
import urllib
import cookielib
def login():
email = raw_input("请输入用户名:")
pwd = raw_input("请输入密码:") data={"email":email,"password":pwd}
post_data=urllib.urlencode(data) cj=cookielib.CookieJar()
opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))headers
={"User-agent":"Mozilla/4.0 (compatibleMSIE 6.0Windows NT 5.1"}website =
raw_input('请输入网址:')req=urllib2.Request(website,post_data,headers)content=opener.open(req)print
content.read()
2.使用selenium
import selenium import webdriver
browser=webdriver.Firefox()
browser.get("Url")
browser.find_element_by_id(" ").sendkey("username")
browser.find_element_by_id(" ").sendkey("pass")
browser.find_element_by_id(" ").click()
其实我这个最简单了,用的python3,requests, 只需要验证一次,就会保存cookies,下次登录使用cookies登录。
第一步、打开首页获取_xref值,验证图片 第二步、输入账号密码 第三步、看是否需要验证、要则下载验证码图片,手动输入
第四步、判断是否登录成功、登录成功后获取页面值。