爬虫笔记(1)

以前学习爬虫的 一些笔记 
json.dumps是将dict转化成str格式,json.loads是将str转化成dict格式
json.dumps实现python类型转化为json字符串,返回一个str对象 把一个Python对象编码转换成Json字符串
json.loads把Json格式字符串解码转换成Python对象 从json到python的类型转换


 # mongodb insert的参数必须是Python的数据类型, json.loads()将data转为Python的数据类型   !!!!!!!!!
 
 
 # ------------------------------------------------------------------------------------------------------------------
#  from bs4 import BeautifulSoup
soup = BeautifulSoup('<a onclick="xx" href="xx">xx</a>', 'html.parser')
a = soup.select('a')[0]
onclick = a.get('onclick')
print(onclick)  #xx
获得一个元素后,使用get('attr')可以得到value

string 方法,输出结果与当前唯一子节点的 .string 结果相同。
通俗点说就是:如果一个标签里面没有标签了,那么 .string 就会返回标签里面的内容。
如果标签里面只有唯一的一个标签了,那么 .string 也会返回最里面的内容。
如果超过一个标签的话,那么就会返回None
print soup.head.string  
#The Dormouse's story  
print soup.title.string  
#The Dormouse's story 

print soup.html.string  
# None 

  #***find_all( name , attrs , recursive , text , **kwargs )***********!!!!!!!!!!!!!!
find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件
1  name 参数
name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉
#第一个参数为Tag的名称   
tag.find_all(‘title’)    
#得到”<title>&%^&*</title>”,结果为一个列表    
  
#第二个参数为匹配的属性  
tag.find_all(“title”,class=”sister”)     
#得到如”<title class = “sister”>%^*&</title>    
  
# 第二个参数也可以为字符串,得到字符串匹配的结果  
tag.find_all(“title”,”sister”)    
#得到如”<title class = “sister”>%^*&</title> 

A下面的例子用于查找文档中所有的<b>标签
soup.find_all('b')  
# [<b>The Dormouse's story</b>]  
B.传正则表达式
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,
这表示<body>和<b>标签都应该被找到
import re  
for tag in soup.find_all(re.compile("^b")):  
    print(tag.name)  
# body  
# b  
C.传列表
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签
soup.find_all(["a", "b"])  
# [<b>The Dormouse's story</b>,  
#  <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,  
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,  
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]  
D.传 True
True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
E.传方法
2)keyword 参数
注意:如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,
如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性
soup.find_all(id='link2')  
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>] 
如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性 
soup.find_all(href=re.compile("elsie"))  
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
使用多个指定名字的参数可以同时过滤tag的多个属性
soup.find_all(href=re.compile("elsie"), id='link1')  
# [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]  
在这里我们想用 class 过滤,不过 class 是 python 的关键词,这怎么办?加个下划线就可以
soup.find_all("a", class_="sister")  
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,  
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,  
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]  
可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag
data_soup.find_all(attrs={"data-foo": "value"})  
# [<div data-foo="value">foo!</div>] 
4)limit 参数
soup.find_all("a", limit=2)  
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,  
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]   

CSS选择器     用到的方法是 soup.select(),返回类型是 list   在写 CSS 时,标签名不加任何修饰,类名前加点 .      id名前加 #

(1)通过标签名查找
rint soup.select('title')   
#[<title>The Dormouse's story</title>]  
(2)通过类名查找
print soup.select('.sister')  
(3)通过 id 名查找
print soup.select('#link1')  
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]  
(4)组合查找   查找 p 标签中,id 等于 link1的内容,二者需要用空格分开
print soup.select('p #link1')  
     直接子标签查找
	 print soup.select("head > title")  
	 #[<title>The Dormouse's story</title>] 
(5)属性查找
查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到
print soup.select('a[class="sister"]')  
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, 
print soup.select('a[href="http://example.com/elsie"]')  
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>] 	
上的 select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容
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()  
	
例如  item['home_page'] = cpy1.find(class_="link-line").find_all('a')[-1].get_text().strip()

#---------------------------------------------------------------------------------------------
只有css选择器才能用 .  #   find_all 不可以使用
# --------------------------------------------------------------------------------------------------------------------------
字典中的get()方法取不到会返回None, 直接用键名取的话 取不到就报错。   json.loads可以吧str 转换成字典格式, 吧json格式数据转换成python对象

因为dumps处理中文的时候默认使用ascii,会让中文无法显示,所以要通过ensure_ascii=False,忽略ascill编码,
但是又由于py2默认编码是ascii,如果忽略了也不会正常显示,所以要把py2默认编码改为utf8
将解释器的默认编码转为utf-8:
      import sys
      reload(sys)
      sys.setdefaultencoding("utf-8")


# ---------------------------------------------------------------------------------------------------------------------------
# selenium

四、元素交互操作-搜索框传入关键词进行自动搜索   结合爬取淘宝信息的案列
from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')#找到搜索框
input.send_keys('iPhone')#传送入关键词
time.sleep(5)
input.clear()#清空搜索框
input.send_keys('男士内裤')
button = browser.find_element_by_class_name('btn-search')#找到搜索按钮
button.click()
hmtl = driver.page_source  # 获取网页源代码

# 从Selenium 类库里导入webdriver模块
from selenium import webdriver
# 调用指定的浏览器,创建webdriver对象(浏览器对象)
driver = webdriver.PhantomJS()
# 通过浏览器获取指定页面的数据,当发送请求后,会建立一个标签页显示网页内容
driver.get("http://www.baidu.com/")
# 保存网页源码
hmtl = driver.page_source
# 保存当前标签页的截图
driver.save_screenshot("baidu.png")
# 查找页面指定的元素,并执行点击事件
driver.find_element_by_name("tj_trnews").click()
driver.save_screenshot("baidu.png")
# 查找页面指定的元素,   并输入文字(必须是Unicode)
driver.find_element_by_id("ww").send_keys(u"双11")
driver.save_screenshot("baidu.png")
driver.find_element_by_class_name("btn").click()
driver.save_screenshot("baidu.png")
# 找到指定的元素,并执行点击事件,如果该页面需要新建标签页打开,则新建标签页
driver.find_element_by_xpath("//div[@id='1']//a").click()
driver.save_screenshot("baidu.png")
# 获取所有标签页窗口句柄
print driver.window_handles
# 根据窗口句柄切换到指定的标签页   下标 应该是从0开始
driver.switch_to_window(driver.window_handles[1])
driver.save_screenshot("baidu.png")
# 打印标签页标题
print driver.title
# 打印该页面的url地址
print driver.current_url
driver.switch_to_window(driver.window_handles[0])
print driver.title
# 获取当前页面的Cookie
print driver.get_cookies()

获取文本值
from selenium import webdriver
browser = webdriver.Chrome()
url = 'https://www.zhihu.com/explore'
browser.get(url)
input = browser.find_element_by_class_name('zu-top-add-question')
print(input.text)#input.text文本值
browser.close()


九、等待

隐式等待
当使用了隐式等待执行测试的时候,如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常,
换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0

from selenium import webdriver

browser = webdriver.Chrome()
browser.implicitly_wait(10)#等待十秒加载不出来就会抛出异常,10秒内加载出来正常返回
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)

显式等待
指定一个等待条件,和一个最长等待时间,程序会判断在等待时间内条件是否满足,如果满足则返回,如果不满足会继续等待,超过时间就会抛出异常
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_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
print(input, button)

title_is 标题是某内容
title_contains 标题包含某内容
presence_of_element_located 元素加载出,传入定位元组,如(By.ID, 'p')    ########
visibility_of_element_located 元素可见,传入定位元组
visibility_of 可见,传入元素对象
presence_of_all_elements_located 所有元素加载出
text_to_be_present_in_element 某个元素文本包含某文字                        ######
text_to_be_present_in_element_value 某个元素值包含某文字
frame_to_be_available_and_switch_to_it frame加载并切换
invisibility_of_element_located 元素不可见
element_to_be_clickable 元素可点击
staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新
element_to_be_selected 元素可选择,传元素对象
element_located_to_be_selected 元素可选择,传入定位元组
element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回False
element_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回False
alert_is_present 是否出现Alert

详细内容:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions

十一、前进后退-实现浏览器的前进后退以浏览不同的网页
import time
from selenium import webdriver

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

十二、Cookies
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())

选项卡管理 增加浏览器窗口
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('http://www.fishc.com')

十三、异常处理
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.find_element_by_id('hello')

from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()
# -----------------------------------------------------------------------------------------------------------

# xpath 的使用
from lxml import etree
# 将html字符串转为HTML DOM
hmtl_obj = etree.HTML(html)
result_list = html_obj.xpath("//div[@id='xxx']/p/text()")                      #  Xpath 为: //cell[data[text()='Alpha'] and data[@type='String']]     node_list = response.xpath("//tr[@class='even'] | //tr[@class='odd']")
lxml 会帮助我们规范 网页的HTML字符串

由于在response中使用XPath、CSS查询十分普遍,因此,Scrapy提供了两个实用的快捷方式: response.xpath() 及 response.css():
response.xpath('//title/text()')
response.css('title::text')
.xpath() 及 .css() 方法返回一个类 SelectorList 的实例, 它是一个新选择器的列表。这个API可以用来快速的提取嵌套数据。为了提取真实的原文数据,你需要调用 .extract() 方法如下:

response.css('img').xpath('@src').extract()
如果你只想要第一个匹配的元素,可以使用·.extract_first()·:
注意CSS选择器可以使用CSS3伪元素(pseudo-elements)来选择文字或者属性节点:
response.css('title::text').extract()

Selector 有一个 .re() 方法,用来通过正则表达式来提取数据。不同于使用 .xpath() 或者 .css() 方法, .re() 方法返回unicode字符串的列表,
所以无法构造嵌套式的 .re() 调用。

下面是一个例子,从上面的 HTML code 中提取图像名字:
response.xpath('//a[contains(@href, "image")]/text()').re(r'Name:\s*(.*)')
# ----------------------------------------------------------------------------------------------------------------
#jsonpath的使用
类似于XPath在xml文档中的定位,JsonPath表达式通常是用来路径检索或设置Json的
..  不管位置选择所有符合的条件
@   现行节点
$   根节点
[]  迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等 )  支持切片
[,] 支持迭代器中做多选。
*   匹配所有元素
?() 支持过滤操作
.or[] 取子节点

(也可以不用jsonpath我们可以吧json类型转换成python类型然后从字典中取值看即可)

jsonpath的使用方法
import jsonpath
# 把json格式字符串转换成python对象 注意如果数据本来就是一个python对象数据 就不需要转了  比如requests.get().json
jsonobj = json.loads(html)
# 从根节点开始,匹配name节点
citylist = jsonpath.jsonpath(jsonobj,'$..name')


# ----------------------------------------------------------------------------------------------------------------
#  format
In [2]: '{},{}'.format('kzc',18) 
Out[2]: 'kzc,18
In [1]: '{0},{1}'.format('kzc',18) 
Out[1]: 'kzc,18
In [5]: '{name},{age}'.format(age=18,name='kzc') 
Out[5]: 'kzc,18
# ---------------------------------------------------------------------------------------------------------------------
检查网页是否动是态加载的 查看网页源代码,ctrl f 搜索网页中的信息看看是否是动态加载
# --------------------------------------------------------------------------------------------------------------------
百度传课 爬虫笔记
html = urlopen(url, data=None, timeout=<..>,cafile=None,capath=None)
ca 这些参数大部分都是身份验证 不常用
print html.geturl() 返回的是response的URL信息
print html.headers 返回协议信息等
print html.getcode() 返回response状态码 通常为200   404没有找到该网站
# ----------------------------------------------------------------------------------------------------------

在pycharm里面的终端可以进行搜索ctrl f   可以用和这个方法在终端查看获取的HTML信息是否完整    还可以替换代码中的某些东西  支持正则
我们获取一定要看获取的网页有没有我们想要的数据 有时候我们第一次拿到的只是一个框架 我们想要的数据是通过ajax 加载的
然后我们知道是ajax返回的数据后 不要盲目的吧头部信息组装向这个网站发送请求, 一定要看看请求方式 是get还是post

.json 返回的是一个python类型的!!!字典!!! 如果获取的是json 数据,通过字典的键取得我们想要的数据后 然后data= json.dumps(position,ensure_ascii=False)
然后写入文件 的时候要进行encode('utf-8')的编码  很重要  (爬虫课件2.6 )

在构建headers的时候一定要注意不要有空格
# ----------------------------------------------------------------------------------------------------------
# requests 

 r = requests.get('http://www.zhidaow.com')  # 发送请求
 r.status_code  # 返回码 
 r.text
 r.url
 r.content   #是以字节的方式去显示,所以在IDLE中以b开头
 r.encoding  #来获取网页编码。
 r.json()    #返回的时候json数据
 
 proxy = { "http": "mr_mao_hacker:[email protected]:16816" } # 私密代理
 proxies = {"http": "http://12.34.56.79:9527"} # 使用代理
 requests.get(url,params= '',headers='',proxies = proxies)
 # 查看响应内容,response.text 返回的是Unicode格式的数据
print response.text
# 查看响应内容,response.content返回的字节流数据
print respones.content
requests.post(url, data = formdata, headers = headers)

处理HTTPS请求 SSL证书验证 (处理需要ssl验证的网站) 
response = requests.get("https://www.baidu.com/", verify=False)  # 忽略ssl证书

#-------------------------------------
python 逻辑运算符
and    or    not     in      not in       is     is not


import redis
class RedisHelper():
    def __init__(self,host='localhost',port=6379):
        self.__redis = redis.StrictRedis(host, port)
    def get(self,key):
        if self.__redis.exists(key):
            return self.__redis.get(key)
        else:
            return ""
    def set(self,key,value):
        self.__redis.set(key,value)

# ------------------------------------------------

string.replace().replace()  多个进行替换的时候
也可以进行循环替换 for x  in xx:   replace   当然了也可以用正则中的	sub(正则,替换成XX,数据源)



.split(',') 分割  可以将字符串变成列表
'|'.join 是合并 可以把 列表变成字符串的形式



猜你喜欢

转载自blog.csdn.net/redpintings/article/details/80745128
今日推荐