“web抓取”是一个术语,即利用程序下载并处理来自web的内容。
▎在python中,有几个模块能让抓取网页变得很容易。
webbrowser:python自带,打开游览器获取指定页面。
requests:从因特网上下载文件和网页。
Beautiful Soup:解析HTML,即网页编写的格式。
selenium:启动并控制一个web游览器。selenium能够填写表单,并模拟鼠标在这个游览器中点击。
webbrowser模块
webbrowser模块的open()函数可以启动一个新游览器,打开指定的URL。
>>> import webbrowser >>> webbrowser.open(‘http://www.baidu.com‘)
requests模块
requests模块能很容易从web下载文件,不必担心一些复杂的问题,诸如网络错误、连接问题和数据压缩。
requests模块不是python自带的,所以必须先通过pip安装。
编写requests模块是因为python的urllib2模块用起来太复杂。如果需要从web下载东西,还是使用requests模块更方便。
[root@juispan ~]# pip install requests Collecting requests Downloading requests-2.18.2-py2.py3-none-any.whl (88kB) 100% |████████████████████████████████| 92kB 75kB/s Collecting chardet<3.1.0,>=3.0.2 (from requests) Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB) 100% |████████████████████████████████| 143kB 75kB/s Collecting urllib3<1.23,>=1.21.1 (from requests) Downloading urllib3-1.22-py2.py3-none-any.whl (132kB) 100% |████████████████████████████████| 133kB 21kB/s Collecting certifi>=2017.4.17 (from requests) Downloading certifi-2017.7.27.1-py2.py3-none-any.whl (349kB) 100% |████████████████████████████████| 358kB 27kB/s Collecting idna<2.6,>=2.5 (from requests) Downloading idna-2.5-py2.py3-none-any.whl (55kB) 100% |████████████████████████████████| 61kB 36kB/s Installing collected packages: chardet, urllib3, certifi, idna, requests Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.5 requests-2.18.2 urllib3-1.22
requests.get()函数接受一个要下载的URL字符串。通过在requests.get()的返回值上调用type(),返回一个Response对象,其中包含了web服务器对请求做出的响应。
通过检查Response对象的status_code属性,可以了解对这个网页的请求是否成功。如果该值等于requests.codes.ok,那么一切都好。
如果请求成功,下载的页面就作为一个字符串,保存在Response对象的text变量中。
>>> import requests >>> res=requests.get(‘https://wkbos.bdimg.com/v1/wenku1//......=2017-07-30T13:23:41Z‘) >>> type(res) <class ‘requests.models.Response‘> >>> res.status_code==requests.codes.ok True >>> len(res.text) 25663 >>> print(res.text[:100]) 1. 阅读须知 文中使用 作为会命令行中的输出信息的前缀 对于不清楚用用途的函数可以在解释器下面输入 help(函数名)来获取相关信息 另外,自带的文档和goo
除了status_code属性检查是否成功,还有一种简单的方法,就是在Response对象上调用raise_for_status()方法。如果下载文件出错,将抛出异常;如果下载成功,就什么也不做。
raise_for_status()方法是一种很好的方式,确保程序在下载失败时停止。可以用try和except语句将raise_for_status()代码包裹起来,处理这一错误,不让程序崩溃。
总是在调用requests.get()之后再调用raise_for_status()。确保下载确实成功,然后再让程序继续。
>>> res=requests.get(‘http://nostarch.com‘) >>> res.raise_for_status() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/site-packages/requests/models.py", line 937, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: http://nostarch.com/
将下载的文件保存到硬盘,可以用标准的open()函数和write()方法,但必须用“写二进制(wb)”模式打开该文件,作为open()的第二参数。
即使该页面是纯文本的,也需要写入二进制数据,而不是文本数据,目的是为了保存该文本中的“unicode编码”。
为了将web页面写入到一个文件,可以用for循环和Response对象的iter_content()方法。
>>> import requests >>> res=requests.get(‘http://www.gutenberg.org/cache/epub/1112/pg1112.txt‘) >>> res.raise_for_status() >>> playFile=open(‘123.txt‘,‘wb‘) >>> for text in res.iter_content(100000): ... playFile.write(text) ... >>> playFile.close()
BeautifulSoup模块
HTML简介
超文本标记语言(HTML)是编写web页面的格式。
HTML中有许多不同的标签。有一些标签具有额外的特性,在尖括号内以“属性”的方式展现。
某些元素具有id属性,可以用来在页面上唯一地确定该元素。
程序可以根据元素的id属性来寻找它。开发者要弄清楚元素的id属性,这是编写web抓取程序常见的任务。
不要用正则表达式来解析HTML。在一个字符串中定位特定的一段HTML,这似乎很适合使用正则表达式。但是,不建议这么做。HTML的格式可以有很多不同的方式,并且仍然被认为是有效的HTML,但尝试用正则表达式来捕捉所有这些可能的变化,将非常繁琐,并且容易出错。专门用于解析HTML的模块,诸如Beautiful Soup,将更不容易导致缺陷。
Beautiful Soup是一个模块,用于从HTML页面中提取信息。它的名称是bs4,通过pip安装(pip install beautifulsoup4),导入使用命令import bs4。
针对要寻找的元素,调用method()方法,传入一个字符串作为CSS“选择器”。选择器就像正则表达式:它们指定了要寻找的模式。
[root@juispan ~]# pip install beautifulsoup4 Collecting beautifulsoup4 Downloading beautifulsoup4-4.6.0-py2-none-any.whl (86kB) 100% |████████████████████████████████| 92kB 540kB/s Installing collected packages: beautifulsoup4 Successfully installed beautifulsoup4-4.6.0
>>> import requests,bs4 >>> res=requests.get(‘http://www.baidu.com‘) >>> res.raise_for_status() >>> bs=bs4.BeautifulSoup(res.text,‘html.parser‘) >>> type(bs) <class ‘bs4.BeautifulSoup‘>
▎CSS选择器举例:
soup.select(‘div‘) 所有名为<div>的元素
soup.select(‘#author‘) 带有id属性为author的元素
soup.select(‘p#author‘) 所有id属性为author的元素,只要它也在一个<p>元素之内
soup.select(‘.notice‘) 所有使用CSS class属性名为notice的元素
soup.select(‘div span‘) 所有在<div>元素之内的<span>元素
soup.select(‘div>span‘) 所有直接在<div>元素之内的<span>元素,中间没有其他元素
soup.select(‘input[name]‘) 所有名为<input>,并有一个name属性,其值无所谓的元素
soup.select(‘input[type="button"]‘) 所有名为<input>,并有一个type属性,其值为button的元素
不同的选择器模式可以组合起来,形成复杂的匹配。
select()方法将返回一个Tag对象的列表,这是Beautiful Soup表示一个HTML元素的方式。
针对BeautifulSoup对象的HTML的每次匹配,列表中都有一个Tag对象。
Tag值可以传递给str()函数,显示它们代表HTML标签。
Tag值也可以有attrs属性,它将该Tag的所有HTML属性作为一个字典。
Tag对象的get()方法让我们很容易从元素中获取属性值。向该方法传入一个属性名称的字符串,它将返回该属性的值。
>>> import requests,bs4 >>> exampleFile=requests.get(‘http://www.baidu.com‘) >>> exampleBS=bs4.BeautifulSoup(exampleFile.text,‘html.parser‘) >>> elems=exampleBS.select(‘a‘) >>> type(elems) <type ‘list‘> >>> len(elems) 11 >>> type(elems[0]) <class ‘bs4.element.Tag‘> >>> elems[0].getText() u‘\xe6\x96\xb0\xe9\x97\xbb‘ >>> str(elems[0]) ‘<a class="mnav" href="http://news.baidu.com" name="tj_trnews">\xc3\xa6\xc2\x96\xc2\xb0\xc3\xa9\xc2\x97\xc2\xbb</a>‘ >>> elems[0].attrs {u‘href‘: u‘http://news.baidu.com‘, u‘name‘: u‘tj_trnews‘, u‘class‘: [u‘mnav‘]}
selenium模块
selenium模块让python直接控制游览器,实际点击链接,填写登录信息,几乎就像是有一个人类用户在与页面交互。
不推荐使用selenium模块下载文件,会有点慢,并且难以在后台运行。
selenium模块的导入方式:from selenium import webdriver。
使用FireFox方法,首先要在系统里安装火狐游览器。
[root@juispan ~]# pip install selenium Collecting selenium Downloading selenium-3.4.3-py2.py3-none-any.whl (931kB) 100% |████████████████████████████████| 942kB 46kB/s Installing collected packages: selenium Successfully installed selenium-3.4.3
>>> from selenium import webdriver >>> browser=webdriver.FireFox() >>> type(browser) <class ‘selenium.webdriver.firefox.webdriver.WebDriver‘> >>> browser.get(‘http://www.baidu.com‘)
WebDriver对象有好几种方法,用于在页面中寻找元素。它们被分成find_element_*和find_elements_*方法。
find_element_*方法返回一个WebElement对象,代表页面中匹配查询的第一个元素。
find_elements_*方法返回WebElement_*对象的列表,包含页面中所有匹配的元素。
▎WebDriver方法,用于寻找元素:
browser.find_element_by_class_name(name) 使用CSS类name的元素
browser.find_elements_by_class_name(name)
browser.find_element_by_css_selector(selector) 匹配CSS selector的元素
browser.find_elements_by_css_selector(selector)
browser.find_element_by_id(id) 匹配id属性值的元素
browser.find_elements_by_id(id)
browser.find_element_by_link_text(text) 完全匹配提供的text的<a>元素
browser.find_elements_by_link_text(text)
browser.find_element_by_partial_link_text(text) 包含提供的text的<a>元素
browser.find_elements_by_partial_link_text(text)
browser.find_element_by_name(name) 匹配name属性值的元素
browser.find_elements_by_name(name)
browser.find_element_by_tag_name(name) 匹配标签name的元素
browser.find_elements_by_tag_name(name) (大小写无关,<a>元素匹配‘a’和‘A’)
除了*_by_tag_name()方法,所有方法的参数都是区分大小写的。如果没有元素匹配,将会抛出NoSuchElement异常。
▎Webement的属性和方法:
tag_name 标签名,例如‘a’表示<a>元素
get_attribute(name) 该元素name属性的值
text 该元素内的文本,例如<span>hello</span>中的‘hello’
clear() 对于文本字段或文本区域元素,清除其中输入的文本
is_displayed() 如果该元素可见,返回True,否则返回False
is_enabled() 对于输入元素,如果该元素启用,返回True,否则返回False
is_selected() 对于复选框或单选框元素,如果该元素被选中,返回True,否则返回False
location 一个字典,包含键x和y,表示该元素在页面上的位置
find_element_*和find_elements_*方法返回的WebElement对象有一个click()方法,模拟鼠标在该元素上点击。
这个方法用于链接跳转,选择单选按钮,点击提交按钮,或者触发该元素被鼠标点击时发生的任何事情。
向web页面的文本字段发送击键,只要找到那个文本字段的<input>或<textarea>元素,然后调用send_keys()方法。
selenium有一个模块,针对不能用字符串值输入的键盘击键。它的功能非常类似转义字符。
这些值保存在selenium.webdriver.common.keys模块的属性中。由于这个模块名较长,建议from selenium.webdriver.common.keys import Keys。
▎selenium.webdriver.common.keys模块中常用的变量:
Keys.DOWN,Keys.UP,Keys.LEFT,Keys.RIGHT 键盘箭头键
Keys.ENTER,Keys.RETURN 回车和换行键
Keys.HOME,Keys.END,Keys.PAGE_DOWN,Keys.PAGE_UP HOME键、END键、Page Up键、Page Down键
Keys.ESCAPE,Keys.BACK_SPACE,Keys.DELETE Esc、Backspace和Delete键
Keys.F1,Keys.F2,...,Keys.F12 键盘顶部的F1到F12键
Keys.TAB Tab键
▎利用以下的方法,selenium也可以模拟点击各种游览器按钮:
browser.back()点击“返回”按钮。
browser.forward()点击“前进”按钮。
browser.refresh()点击“刷新”按钮。
browser.quit()点击“关闭窗口”按钮。
本文出自 “A man & A computer” 博客,请务必保留此出处http://juispan.blog.51cto.com/943137/1952156
原文:http://juispan.blog.51cto.com/943137/1952156