python 版本:基于python2.7的稳定版
爬虫
Fiddler
urlopen:向指定的url发送请求,并返回服务器响应的类文件对象
“`
import urllib2
response == urllib2.urlopen(‘http://www.baidu.com‘)
# 类文件对象支持文件对象的操作方法,如read()方法,读取文件的全部内容,返回字符串
html = response.read()
“`
Request
urlopen的参数,用来增加HTTP报头信息
import urllib2
request = urllib2.Request('http://www.baidu.com')
response = urllib2.urlopen(request)
html = response.read()
Request除了必须要有url参数之外,还可以设置另外两个参数
User-Agent
在正常的请求中,请求者的身份应该是正常的,如果使用诸如‘python2.7’请求网页,显然是明示自己是爬虫,应该避免,需要伪装请求身份,也就是自定义User-Agent
# IE 9.0 的 User-Agent,包含在 user_agent里
user_agent = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"}
# url 连同 headers,一起构造Request请求,这个请求将附带 IE9.0 浏览器的User-Agent
request = urllib2.Request(url, headers = user_agent)
添加更多的Headers信息
Request.add_header(key,value)
查看已有的header:Request.get_geader(header_name="...")
user_agent = random.choice(UA_list)
Urllib2默认只支持HTTP/HTTPS的GET和POST方法
urllib提供了urlencode方法来产生GET查询字符串,而urllib2没有。(这是urllib和urllib经常在一起用的主要原因)
ipyhon中测试:
import urllib
word = {"name":"michael"}
urllib.urlencode(word)
out:"name=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2"
print urllib.unquote("name=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2")
out:name="michael"
作为一名爬虫工程师,要始终关注数据的来源
表单数据可以作为URL字段(method=’get’)或者HTTP POST(method=“post”)的方式来发送。
在爬虫过程中,可以忽略ssl证书的验证来跳过对于https网站的访问
但是基本的urlopen()方法不支持代理,Cookie等其他的HTTP/HTTPS高级功能,要像支持这些功能
注意:如果程序里所有的请求都是使用自定义的opener,可以使用urllib.install_opener()将自定义的opener对象定义为全局opener,表示之后如果调用urlopen,都将使用这个opener
import urllib2
# 构建一个HTTPHandler 处理器对象,支持处理HTTP请求
http_handler = urllib2.HTTPHandler()
# 调用urllib2.build_opener()方法,创建支持处理HTTP请求的opener对象
opener = urllib2.build_opener(http_handler)
# 构建 Request请求
request = urllib2.Request("http://www.baidu.com/")
# 调用自定义opener对象的open()方法,发送request请求
# (注意区别:不再通过urllib2.urlopen()发送请求)
response = opener.open(request)
# 获取服务器响应内容
print response.read()
urllib2.ProxyHandler({"http":"124.88.67.81.80"})
ProxyBsicAuthHandler()
HttpBasicHandler()
cookielib和HTTPCookieProcessor
import urllib
import urllib2
import cookielib
# 1. 构建一个CookieJar对象实例来保存cookie
cookie = cookielib.CookieJar()
# 2. 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
cookie_handler = urllib2.HTTPCookieProcessor(cookie)
# 3. 通过 build_opener() 来构建opener
opener = urllib2.build_opener(cookie_handler)
# 4. addheaders 接受一个列表,里面每个元素都是一个headers信息的元祖, opener将附带headers信息
opener.addheaders = [("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36")]
# 5. 需要登录的账户和密码
data = {"email":"[email protected]", "password":"alaxxxxxime"}
# 6. 通过urlencode()转码
postdata = urllib.urlencode(data)
# 7. 构建Request请求对象,包含需要发送的用户名和密码
request = urllib2.Request("http://www.renren.com/PLogin.do", data = postdata)
# 8. 通过opener发送这个请求,并获取登录后的Cookie值,
opener.open(request)
# 9. opener包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面
response = opener.open("http://www.renren.com/410043129/profile")
# 10. 打印响应内容
print response.read()
一般get请求
response = request.get('http://www.baidu.com')
get请求添加headers和查询参数
import requests
kw = {'wd':'长城'}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
response = requests.get("http://www.baidu.com/s?", params = kw, headers = headers)
# 查看响应内容,response.text 返回的是Unicode格式的数据
print response.text
# 查看响应内容,response.content返回的字节流数据
print respones.content
# 查看完整url地址
print response.url
# 查看响应头部字符编码
print response.encoding
# 查看响应码
print response.status_code
基本POST请求
requests.post('http://www.baidu.com', data = data)
import requests
formdata = {
"type":"AUTO",
"i":"i love python",
"doctype":"json",
"xmlVersion":"1.8",
"keyfrom":"fanyi.web",
"ue":"UTF-8",
"action":"FY_BY_ENTER",
"typoResult":"true"
}
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}
response = requests.post(url, data = formdata, headers = headers)
print response.text
# 如果是json文件可以直接显示
print response.json()
代理(proxies参数)
import requests
# 根据协议类型,选择不同的代理
proxies = {"http": "http://12.34.56.79:9527"}
response = requests.get("http://www.baidu.com", proxies = proxies)
print response.text
私密代理
import requests
# 如果代理需要使用HTTP Basic Auth,可以使用下面这种格式:
proxy = { "http": "mr_mao_hacker:[email protected]:16816" }
response = requests.get("http://www.baidu.com", proxies = proxy)
print response.text
Web客户端验证
import requests
auth=('test', '123456')
response = requests.get('http://192.168.199.107', auth = auth)
print response.text
cookies和session
import requests
response = requests.get("http://www.baidu.com/")
# 7. 返回CookieJar对象:
cookiejar = response.cookies
# 8. 将CookieJar转为字典:
cookiedict = requests.utils.dict_from_cookiejar(cookiejar)
print cookiejar
print cookiedict
session
import requests
# 1. 创建session对象,可以保存Cookie值
ssion = requests.session()
# 2. 处理 headers
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
# 3. 需要登录的用户名和密码
data = {"email":"[email protected]", "password":"alarmchime"}
# 4. 发送附带用户名和密码的请求,并获取登录后的Cookie值,保存在ssion里
ssion.post("http://www.renren.com/PLogin.do", data = data)
# 5. ssion包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面
response = ssion.get("http://www.renren.com/410043129/profile")
# 6. 打印响应内容
print response.text
处理HTTPS请求的SSL证书验证
response = requests.get('http://www.12306.cn/moremhweb', verify=False)
数据处理
非结构化数据
结构化数据处理
正则表达式
使用步骤
3.最后使用Match对象提供的属性和方法获得信息,根据需要进行其他操作
示例:
>>> import re
>>> pattern = re.compile(r'\d+') # 用于匹配至少一个数字
>>> m = pattern.match('one12twothree34four') # 查找头部,没有匹配
>>> print m
None
XML
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italiantitle>
<author>Giada De Laurentiisauthor>
<year>2005year>
<price>30.00price>
book>
<book category="children">
<title lang="en">Harry Pottertitle>
<author>J K. Rowlingauthor>
<year>2005year>
<price>29.99price>
book>
<book category="web">
<title lang="en">XQuery Kick Starttitle>
<author>James McGovernauthor>
<author>Per Bothnerauthor>
<author>Kurt Cagleauthor>
<author>James Linnauthor>
<author>Vaidyanathan Nagarajanauthor>
<year>2003year>
<price>49.99price>
book>
<book category="web" cover="paperback">
<title lang="en">Learning XMLtitle>
<author>Erik T. Rayauthor>
<year>2003year>
<price>39.95price>
book>
bookstore>
XPath
选取节点
谓语
lxml库
# lxml_test.py
# 使用 lxml 的 etree 库
from lxml import etree
text = '''
<div>
- class="item-0">"link1.html">first item
- class="item-1">"link2.html">second item
- class="item-inactive">"link3.html">third item
- class="item-1">"link4.html">fourth item
- class="item-0">"link5.html">fifth item # 注意,此处缺少一个
闭合标签
div>
'''
#利用etree.HTML,将字符串解析为HTML文档
html = etree.HTML(text)
# 按字符串序列化HTML文档
result = etree.tostring(html)
print(result)
<html><body>
<div>
<ul>
<li class="item-0"><a href="link1.html">first itema>li>
<li class="item-1"><a href="link2.html">second itema>li>
<li class="item-inactive"><a href="link3.html">third itema>li>
<li class="item-1"><a href="link4.html">fourth itema>li>
<li class="item-0"><a href="link5.html">fifth itema>li>
ul>
div>
body>html>
# lxml_parse.py
from lxml import etree
# 读取外部文件 hello.html
html = etree.parse('./hello.html')
result = etree.tostring(html, pretty_print=True)
print(result
输出结果和上面的结果相同
示例1: 获取所有的
# xpath_li.py
from lxml import etree
html = etree.parse('hello.html')
print type(html) # 显示etree.parse() 返回类型
result = html.xpath('//li')
print result # 打印- 标签的元素集合
print len(result)
print type(result)
print type(result[0])
# xpath_li.py
from lxml import etree
html = etree.parse('hello.html')
result = html.xpath('//li/@class')
print result
用法示例
# beautifulsoup4_test.py
from bs4 import BeautifulSoup
html = """
<html><head><title>The Dormouse's storytitle>head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's storyb>p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">a>,
<a href="http://example.com/lacie" class="sister" id="link2">Laciea> and
<a href="http://example.com/tillie" class="sister" id="link3">Tilliea>;
and they lived at the bottom of a well.p>
<p class="story">...p>
"""
#创建 Beautiful Soup 对象
soup = BeautifulSoup(html)
#打开本地 HTML 文件的方式来创建对象
#soup = BeautifulSoup(open('index.html'))
#格式化输出 soup 对象的内容
print soup.prettify()
BeautifulSoup将复杂的HTML文档转换成一个复杂的树形结构,每个节点都是python对象,所有的对象可以归纳成4种
遍历文档树
搜索文档树
find_all(name, attrs, recursive, text, **kwargs)
soup.find_all('b')
,查找所有的b标签soup.find_all(re.conpile('^b'))
,查找所有的b标签soup.find_all(['a','b'])
,查找文档树中的所有\标签 和 \标签,返回一个列表soup.find_all(class_='sister')
:查询所有的类属性为‘sister’的标签,返回列表soup.find_all(id='link2')
:查询所有的id属性为link2的标签,返回一个列表 text参数
soup.find_all(text='Elsia'):查询所有的'Elsie'字符串,返回一个列表
soup.find_all(text=['Tillie', 'Elisia', 'Lacie']):查询所有的包含’Tillie‘,'Elisia','Lacie'的字符串,返回一个列表
soup.find_all(text=re.compile(r'Dormouse')):查询所有的含有Dormouse的字符串,返回一个列表
find
css 选择器
soup.select()
,返回的类型为listprint soup.select('title')
#[<title>The Dormouse's storytitle>]
print soup.select('a')
#[<a class="sister" href="http://example.com/elsie" id="link1">a>, <a class="sister" href="http://example.com/lacie" id="link2">Laciea>, <a class="sister" href="http://example.com/tillie" id="link3">Tilliea>]
print soup.select('b')
#[<b>The Dormouse's storyb>]
print soup.select('.sister')
#[<a class="sister" href="http://example.com/elsie" id="link1">a>, <a class="sister" href="http://example.com/lacie" id="link2">Laciea>, <a class="sister" href="http://example.com/tillie" id="link3">Tilliea>]
print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1">a>]
print soup.select('p #link1')
#[<a class="sister" href="http://example.com/elsie" id="link1">a>]
print soup.select('a[class="sister"]')
#[<a class="sister" href="http://example.com/elsie" id="link1">a>, <a class="sister" href="http://example.com/lacie" id="link2">Laciea>, <a class="sister" href="http://example.com/tillie" id="link3">Tilliea>]
print soup.select('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1">a>]
soup = BeautifulSoup(html, 'lxml')
print type(soup.select('title'))
print soup.select('title')[0].get_text()
for title in soup.select('title'):
print title.get_text()
Json
json模块是pythhon自带的,可以直接导入使用,有四个常用功能:dumps,dump,loads,load,用于字符串和python数据类型之间进行转换
# json_loads.py
import json
strList = '[1, 2, 3, 4]'
strDict = '{"city": "北京", "name": "大猫"}'
json.loads(strList)
# [1, 2, 3, 4]
json.loads(strDict) # json数据自动按Unicode存储
# {u'city': u'\u5317\u4eac', u'name': u'\u5927\u732b'}
# json_dumps.py
import json
import chardet
listStr = [1, 2, 3, 4]
tupleStr = (1, 2, 3, 4)
dictStr = {"city": "北京", "name": "大猫"}
json.dumps(listStr)
# '[1, 2, 3, 4]'
json.dumps(tupleStr)
# '[1, 2, 3, 4]'
# 注意:json.dumps() 处理中文时默认使用的ascii编码,会导致中文无法正常显示
print json.dumps(dictStr)
# {"city": "\u5317\u4eac", "name": "\u5927\u732b"}
# 记住:处理中文时,添加参数 ensure_ascii=False 来禁用ascii编码
print json.dumps(dictStr, ensure_ascii=False)
# {"city": "北京", "name": "大刘"}
# json_load.py
import json
strList = json.load(open("listStr.json"))
print strList
# [{u'city': u'\u5317\u4eac'}, {u'name': u'\u5927\u5218'}]
strDict = json.load(open("dictStr.json"))
print strDict
# {u'city': u'\u5317\u4eac', u'name': u'\u5927\u5218'}
# json_dump.py
import json
listStr = [{"city": "北京"}, {"name": "大刘"}]
json.dump(listStr, open("listStr.json","w"), ensure_ascii=False)
dictStr = {"city": "北京", "name": "大刘"}
json.dump(dictStr, open("dictStr.json","w"), ensure_ascii=False)
JsonPath
用法示例:
# jsonpath_lagou.py
import urllib2
import jsonpath
import json
url = 'http://www.lagou.com/lbs/getAllCitySearchLabels.json'
request =urllib2.Request(url)
response = urllib2.urlopen(request)
html = response.read()
# 把json格式字符串转换成python对象
jsonobj = json.loads(html)
# 从根节点开始,匹配name节点
citylist = jsonpath.jsonpath(jsonobj,'$..name')
print citylist
print type(citylist)
fp = open('city.json','w')
content = json.dumps(citylist, ensure_ascii=False)
print content
fp.write(content.encode('utf-8'))
fp.close()
UTF-8与GBK互相转换,那就先把UTF-8转换为Unicode,在从Unicode转换为GBK,反之同理
# 这是一个 UTF-8 编码的字符串
utf8Str = "你好地球"
# 1. 将 UTF-8 编码的字符串 转换成 Unicode 编码
unicodeStr = utf8Str.decode("UTF-8")
# 2. 再将 Unicode 编码格式字符串 转换成 GBK 编码
gbkData = unicodeStr.encode("GBK")
# 1. 再将 GBK 编码格式字符串 转化成 Unicode
unicodeStr = gbkData.decode("gbk")
# 2. 再将 Unicode 编码格式字符串转换成 UTF-8
utf8Str = unicodeStr.encode("UTF-8")
decode的作用是将其他编码的字符串转换为Unicode的编码
encode的作用是将Unicode编码转换成其他编码的字符串
JavaScript
jQuery
Ajax
DHTML
那么,对于DHTML,需要采集信息,如何搞定?
Selinium
PhantomJS
使用实例
# IPython2 测试代码
# 导入 webdriver
from selenium import webdriver
# 调用环境变量指定的PhantomJS浏览器创建浏览器对象
driver = webdriver.PhantomJS()
# 如果没有在环境变量指定PhantomJS位置
# driver = webdriver.PhantomJS(executable_path="/usr/local/bin/phantomjs"))
# get方法会一直等到页面被完全加载,然后才会继续程序,通常测试会在这里选择 time.sleep(2)
driver.get("http://www.baidu.com/")
# 获取页面名为 wrapper的id标签的文本内容
data = driver.find_element_by_id("wrapper").text
# 打印数据内容
print data
# 打印页面标题 "百度一下,你就知道"
print driver.title
# 生成当前页面快照并保存
driver.save_screenshot("baidu.png")
# id="kw"是百度搜索输入框,输入字符串"长城"
driver.find_element_by_id("kw").send_keys(u"长城")
# id="su"是百度搜索按钮,click() 是模拟点击
driver.find_element_by_id("su").click()
# 获取新的页面快照
driver.save_screenshot("长城.png")
# 打印网页渲染后的源代码
print driver.page_source
# 获取当前页面Cookie
print driver.get_cookies()
# 调用键盘按键操作时需要引入的Keys包
from selenium.webdriver.common.keys import Keys
# ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
# ctrl+x 剪切输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')
# 输入框重新输入内容
driver.find_element_by_id("kw").send_keys("itcast")
# 模拟Enter回车键
driver.find_element_by_id("su").send_keys(Keys.RETURN)
# 清除输入框内容
driver.find_element_by_id("kw").clear()
# 生成新的页面快照
driver.save_screenshot("itcast.png")
# 获取当前url
print driver.current_url
# 关闭当前页面,如果只有一个页面,会关闭浏览器
# driver.close()
# 关闭浏览器
driver.quit()
鼠标动作链
#导入 ActionChains 类
from selenium.webdriver import ActionChains
# 鼠标移动到 ac 位置
ac = driver.find_element_by_xpath('element')
ActionChains(driver).move_to_element(ac).perform()
# 在 ac 位置单击
ac = driver.find_element_by_xpath("elementA")
ActionChains(driver).move_to_element(ac).click(ac).perform()
# 在 ac 位置双击
ac = driver.find_element_by_xpath("elementB")
ActionChains(driver).move_to_element(ac).double_click(ac).perform()
# 在 ac 位置右击
ac = driver.find_element_by_xpath("elementC")
ActionChains(driver).move_to_element(ac).context_click(ac).perform()
# 在 ac 位置左键单击hold住
ac = driver.find_element_by_xpath('elementF')
ActionChains(driver).move_to_element(ac).click_and_hold(ac).perform()
# 将 ac1 拖拽到 ac2 位置
ac1 = driver.find_element_by_xpath('elementD')
ac2 = driver.find_element_by_xpath('elementE')
ActionChains(driver).drag_and_drop(ac1, ac2).perform()
文字识别是机器视觉的一个分支,是使用一些python库来识别和使用在线图片中的文字
将图像翻译成文字一般被称为 光学文字识别(OCR)。可以实现OCR的底层库并不多,目前很多库都是使用共同的几个底层OCR库,或者在上面进行定制。
在读取和处理图像,图像相关的机器学习以及创建图像等任务中,Python一直都是非常出色的语言。其中一种库叫:Tesseract
Tesseract
import pytesseract
from PIL import Image
image = Image.open('test.jpg')
text = pytesseract.image_to_string(image)
print text
Scrapy使用了Twisted异步网络架构来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求
重要模块
Scrapy的运作流程
制作Scrapy爬出的步骤
scrapy startproject xxx
Scrapy Shell
Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调用代码,也可以用来测试Xpath或者css表达式,查看他们的工作方式,方便我们在爬取的网站中提取数据
启动
scrapy shell "http://www...."
Item Pipeline
Spider
CrawlSpider
Scrapy-redis提供了下面四种组件
Base Spider
总结
搭建scrapy-redis流程