爬虫基础

爬虫的基本原理

什么是爬虫

  • 请求网站并提取数据的自动化程序
  • URL:统一资源定位符

能抓怎样的数据

  • 网页文本
  • 图片,音频,视频
  • 705写入成功

怎么解析

  • 1.直接处理
  • 2.json解析
  • 3.正则表达式
  • 4.bs4
  • 5.pyQuery
  • 6.xpath

怎么解决javascript渲染的问题的?

  • 1.分析ajax请求
  • 2.使用selenium/webDriver
  • 3.splash
  • 4.pyv8或Ghost.py

怎么保存数据

  • 文本型
  • 关系型数据库
  • 非关系型数据库
  • 二进制文件

urllib库详解

什么是urllib(python内置的http库)

  • Urllib.request() 请求模块
  • urllib.error 异常处理模块
  • urllib.parse url解析模块
  • urllib.robotparser robots.txt 解析模块

基本用法

GET请求(例子)
1
2
3
import urllib.request
res = urllib.request.urlopen('http://www.baidu.com')
print(res.read().decode())
POST请求(例子)
1
2
3
4
5
import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({'name':'hello'}),encoding='utf-8')
res = urllib.request.urlopen('http://httpbin.org/post',data=data)
print(res.read().decode())
获取数据并自动保存
1
2
from urllib import request
request.urlretrieve(url='地址',filename='文件名')
设置超时时间
正常
1
2
3
import urllib.request
res = urllib.request.urlopen('http://httpbin.org/get',timeout=1)
print(res.read())
报错
1
2
3
4
5
6
7
8
import socket
import urllib.request
import urllib.error
try:
res = urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason,socket.timeout):
print('time out')
请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import urllib.request
request = urllib.request.Request('http://www.baidu.com') # 生成一个对象
res = urllib.request.urlopen(request)
print(res)

# 增加参数和使用post请求
from urllib import request,parse
url = 'http://www.httpbin.org/post'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
'Host':'httpbin.org'
}
dic = {
'name':'Germey'

}
data = bytes(parse.urlencode(dic),encoding='utf8')
req = request.Request(url=url,data=data,headers=headers,method='POST')
res = request.urlopen(req)
print(res)

# header也可以使用这样
req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',)
响应
1
2
3
4
5
6
7
8
# 响应类型:<class 'http.client.HTTPResponse'>
# 状态码和响应头
import urllib.request
res = urllib.request.urlopen('http://www.baidu.com')
print(res.status) # 状态码
print(res.getheaders()) # 全部响应头
print(res.getheader('Server'))
print(res.read().decode('utf-8')) # 获取响应体内容
代理
1
2
3
4
5
6
7
8
from urllib import request
proxy_header = request.ProxyHandler({
'http':'http://127.0.0.1:8899',
'https':'https://127.0.0.1:8899',
})
opener = request.build_opener(proxy_header)
res = opener.open('http://www.baidu.com')
print(res.read())
异常处理
1
2
3
4
5
6
from urllib import request,error
try:
res = request.urlopen('http://www.baidu.top/11')
print(res.read())
except error.URLError as e:
print(e.reason)
1
2
3
4
5
6
7
8
9
10
from urllib import request,error
try:
res = request.urlopen('http://www.baidu222.top/11')
print(res.read())
except error.HTTPError as e:
print(e.reason,e.code,e.headers)
except error.URLError as e:
print(e.reason)
else:
print('xxxx')
url解析

协议类型:scheme=’http/https’

allow_fragments:#号后的内容存放在哪里

urlunparse:将内容上面返回的内容进行拼接的

urljoin:对两个url进行拼接,以后面的url为标准,有就覆盖,没有就用前面的

import urllib.robotparser :查看那些路径是可以访问的,那些事不可以访问的

re模块的基本使用

常见的使用方法

  • re.S:匹配换行符
  • re.match(正则,带匹配的字符串):尝试从起始位置匹配一个模式,没有返回None
    • group:匹配结果
      • span:匹配的位置
  • re.search :匹配所有能匹配到的,并返回第一个
  • re.sub(正则,要替换的字符串,’字符串’) :
  • re.findall(正则,字符串)
  • re.compile():将正则字符串,编译成一个正则对象

bs4的基本使用方法

lxml的使用方法

1
2
3
4
5
6
7
from lxml import etree
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
'Connection':'close'
}
lxml_obj = etree.HTML(html)
url_list = lxml_obj.xpath('//div[@id="container"]/div')

BeautifulSoup的使用方法

1
2
3
4
5
from bs4 import BeautifulSoup
html = "<html><title class='xxx'>111111</title> "
soup = BeautifulSoup(html,'lxml')
print(soup.prettify()) #自动补全代码
print(soup.title.string)#获取title标签的代码

标签选择器

获取名称
1
print(soup.title.name)
获取属性
1
2
print(soup.p.attrs['name'])
print(soup.p['name'])
获取内容
1
print(soup.p.string)
嵌套选择
1
print(soup.head.title.string)
子节点和子孙节点
1
2
3
print(soup.body.contents) # 返回一个列表
print(soup.body.children) # 放回一个迭代器
soup.body.descendants # 所有的子孙节点,也是一个迭代器
父节点和祖先节点
1
2
print(soup.a.parent) # 父节点,只有一个
soup.a.parents # 祖先节点
兄弟节点
1
2
print(list(soup.p.next_siblings))
print(list(soup.p.previous_siblings))

标准选择器

根据标签
1
print(soup.find_all('ul'))
根据属性
1
2
3
print(soup.find_all(attrs={'id':'list_1'}))
print(soup.find_all(id='list_1'))
print(soup.find_all(class_='p1'))
根据文本
1
print(soup.find_all(text=[777,666,888]))
返回单个元素
1
2
3
4
print(soup.find_parent('title')) :返回父节点
print(soup.find_parents('title')):返回祖先节点
print(soup.find_next_siblings('p')) :返回兄弟节点
print(soup.find_next_sibling('p'))返回兄弟节点

css选择器

1
2
print(soup.select('.p1 .a1'))
print(soup.select('#list_1 .a1'))
获取属性
1
ul["id"]
获取内容
1
2
3
for i in soup.select('#list_1 .a1'):
print(i.get_text())
print(i.text)

pyquery库的使用

基本使用

1
2
3
from pyquery import PyQuery as py
doc = py(url='http://www.baidu.com') # 从url中获取数据
doc = py(filename='demo.html') # 从文件中获取

查找元素

子元素
所有的
1
2
3
doc = py(html)
item = doc('#list_1')
print(item.find('a'))
直接的
1
2
3
doc = py(html)
item = doc('#list_1')
print(item.children())
子元素筛选
1
2
item = doc('#list_1')
print(item.children('.a1'))
父元素
1
2
3
4
5
6
item = doc('#list_1')
print(item.parent()) # 获取父元素
print(item.parents()) # 获取祖先元素
# 对父节点进行筛选
item = doc('#list_1')
print(item.parent('.r1'))
兄弟元素
1
2
3
4
5
item = doc('#list_1')
print(item.siblings()) # 兄弟元素

item = doc('#list_1')
print(item.siblings('.a1')) # 对兄弟元素进行筛选

遍历

单个元素
1
2
item = doc('#list_1')
print(item)
返回迭代器
1
2
item = doc('#list_1').items()
print(item)

获取信息

获取属性
1
2
3
item = doc('#list_1 a')
print(item.attr('href'))
print(item.attr.href)
获取文本
1
item = doc('#list_1 a') print(item.text())
获取html
1
item = doc('#list_1') print(item.html())

DOM操作

addClass和removeClass
1
2
3
item = doc('#list_1')
print(item.remove_class('p1')) :删除p1
print(item.add_class('p1')):添加p1
attr 和 css
1
2
3
item = doc('#list_1')
print(item.attr('name','link'))
print(item.css('font_size','14px'))
remove:把中间a标签全部删除
1
2
3
4
item = doc('#list_1')
print(item.text())
print(item.find('a').remove())
print(item.text())
伪类选择器
1
2
3
4
5
6
7
doc = py(html) 
print(doc('p:first-child')) # 获取第一个
print(doc('p:last-child'))# 获取最后一个
print(doc('p:nth-child(2)'))# 获取第二个
print(doc('p:gt(1)')) # 获取比1大的所有元素
print(doc('p:nth-child(2n)')) # 获取偶数的
print(doc('p:contains(xxx)')) #查看包含xxx文本的所有内容

requests库的基本使用

实例

1
2
3
4
5
6
import requests
res = requests.get('http://www.baidu.com')
print(type(res)) # 获取一个对象
print(res.status_code) # 获取状态码
print(type(res.text)) # 获取页面
print(type(res.cookies)) # 获取cookie

所有请求方式

  • requests.get()
  • requests.post()
  • requests.put()
  • requests.patch()
  • requests.options()
  • requests.head()
  • requests.delete()

获取数据

  • res.json() :获取json数据
  • res.text:获取文本信息
  • res.content :获取二进制数据

响应

  • status_code :获取状态码
  • text:获取文本信息
  • headers:获取头部信息
  • content:获取二进制数据
  • cookies:获取cookie
  • url:访问的url
  • history:历史记录

高级操作

文件上传
1
2
3
import requests
files = {'file':open('11.jpg','rb')}
requests.post('url',files=files)
获取cookie
1
2
3
4
res.cookies.item()
{
111:222
}
会话维持
1
2
3
4
5
import requests
session = requests.session()
session.get('http://httpbin.org/cookies/set/number/1000000')
res = session.get('http://httpbin.org/cookies')
print(res.text)
代理设置
1
2
3
4
5
import requests
proxies = {
'http':'http://127.0.0.1:5000'
}
res = requests.get('http://www.baidu.com',proxies=proxies)
超时设置
1
2
3
4
5
6
7
from requests.exceptions import ReadTimeout
import requests
try:
res = requests.get('http://www.baidu.com',timeout=0.01)
print(res.text)
except ReadTimeout:
print(111)
认证设置
1
res = requests.get('http://www.baidu.com',auth={'user':123})
异常处理
1
2
3
4
5
from requests.exceptions import ReadTimeout, HTTPError,RequestException
ReadTimeout:超时
HTTPError:
ConnectionError:网络不通
RequestException

selenium的基本使用

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

browser = webdriver.Chrome()
try:
browser.get('http://www.baidu.com')
input = browser.find_element_by_id('kw')
input.send_keys('Python')
input.send_keys(Keys.ENTER)
wait = WebDriverWait(browser,10)
wait.until(EC.presence_of_all_elements_located((By.ID,'content_left')))
print(browser.current_url)
print(browser.get_cookies())
print(browser.page_source)
finally:
browser.close()

声明浏览器对象

1
2
3
4
5
6
from selenium import webdriver 
browser = webdriver.Chrome() # chrome浏览器
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()

访问页面

1
2
3
4
5
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://www.taobao.com')
print(browser.page_source)
browser.close()

查找元素

单个元素
第一种
1
2
3
4
5
6
7
8
9
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('http://www.taobao.com')
input_first = browser.find_element_by_id('q')
input_second = browser.find_element_by_css_selector('#q')
input_third = browser.find_element_by_xpath('//*[@id="q"]')
print(input_first,input_second,input_third)
browser.close()
第二种
1
2
3
4
5
6
7
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get('http://www.taobao.com')
input_first = browser.find_element(By.ID,'q')
print(input_first)
browser.close()
多个元素
第一种
1
2
3
4
5
6
7
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('http://www.taobao.com')
lis = browser.find_elements_by_css_selector('.service-bd li')
print(lis)
browser.close()
第二种
1
2
3
4
5
6
7
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get('http://www.taobao.com')
lis = browser.find_elements(By.CSS_SELECTOR,'.service-bd li')
print(lis)
browser.close()

元素交互操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import time

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome()
browser.get('http://www.taobao.com')

input = browser.find_element_by_id('q')
input.send_keys('Iphone')
time.sleep(1)
input.clear()
input.send_keys('iPad')
button = browser.find_element_by_class_name('btn-search')
button.click()
browser.close()

交互动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source= browser.find_element_by_css_selector('#draggable') # 拖拽对象
target= browser.find_element_by_css_selector('#droppable') # 拖拽目标

actions = ActionChains(browser)
actions.drag_and_drop(source,target)
actions.perform()
browser.close()

执行js

1
2
3
4
5
6
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)') # 把下拉到最下面
browser.execute_script('alert("to bottom")')
browser.close()

获取元素信息

获取属性
1
2
3
4
5
6
7
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
logo = browser.find_element_by_id('zh-top-link-logo')
print(logo)
print(logo.get_attribute('class')) # 获取class
browser.close()
获取文本值
1
2
3
4
5
6
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_css_selector('.zh-summary')
print(input.text)
browser.close()
获取id,位置,标签名,大小
1
2
3
4
5
6
7
8
9
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zh-summary')
print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)
browser.close()

Frame:进去和出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult') # 进入里面iframe
source = browser.find_element_by_css_selector('#draggable') # 拖拽对象
print(source)
try:
logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
print('No Logo')
browser.switch_to.parent_frame() # 出来iframe
logo = browser.find_element_by_class_name('logo')
print(logo)
print(logo.text)

等待

隐式等待
1
2
3
4
5
6
7
from selenium import webdriver
browser = webdriver.Chrome()
browser.implicitly_wait(10)
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)
browser.close()
显示等待
1
2
3
4
5
6
7
8
9
10
11
12
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser,10)
input = wait.until(EC.presence_of_all_elements_located((By.ID,'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search')))
print(input,button)
browser.close()

前进和后退

1
2
3
4
5
6
7
8
9
10
11
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('http://www.taobao.com/')
browser.get('http://www.python.org/')
browser.back() # 后退一步
time.sleep(1)
browser.forward() # 前进一步
browser.close()

设置cookie

1
2
3
4
5
6
7
8
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name':'name','domain':'www.zhihu.com','value':'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

选项卡设置

1
2
3
4
5
6
7
8
9
10
11
12
import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()') # 打开一个新的标签
print(browser.window_handles)
browser.switch_to_window(browser.window_handles[1]) # 切换标签
browser.get('https://www.taobao.com')
time.sleep(1)
browser.switch_to_window(browser.window_handles[0])
browser.get('https://python.org')

异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException
browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com')
except TimeoutException:
print('请求超时')
try:
browser.find_element_by_id('hello')
except NoSuchElementException:
print('没有此id')
finally:
browser.close()