以前学习爬虫的 一些笔记
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 是合并 可以把 列表变成字符串的形式