“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)>>> 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 "", line 1, in 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)
▎CSS选择器举例:
soup.select('div') 所有名为 soup.select('#author') 带有id属性为author的元素 soup.select('p#author') 所有id属性为author的元素,只要它也在一个 元素之内 soup.select('.notice') 所有使用CSS class属性名为notice的元素 soup.select('div span') 所有在 soup.select('div>span') 所有直接在 soup.select('input[name]') 所有名为,并有一个name属性,其值无所谓的元素 soup.select('input[type="button"]') 所有名为,并有一个type属性,其值为button的元素 不同的选择器模式可以组合起来,形成复杂的匹配。 select()方法将返回一个Tag对象的列表,这是Beautiful Soup表示一个HTML元素的方式。 针对BeautifulSoup对象的HTML的每次匹配,列表中都有一个Tag对象。 Tag值可以传递给str()函数,显示它们代表HTML标签。 Tag值也可以有attrs属性,它将该Tag的所有HTML属性作为一个字典。 Tag对象的get()方法让我们很容易从元素中获取属性值。向该方法传入一个属性名称的字符串,它将返回该属性的值。 selenium模块 selenium模块让python直接控制游览器,实际点击链接,填写登录信息,几乎就像是有一个人类用户在与页面交互。 不推荐使用selenium模块下载文件,会有点慢,并且难以在后台运行。 selenium模块的导入方式:from selenium import webdriver。 使用FireFox方法,首先要在系统里安装火狐游览器。 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的元素 browser.find_elements_by_link_text(text) browser.find_element_by_partial_link_text(text) 包含提供的text的元素 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’) 除了*_by_tag_name()方法,所有方法的参数都是区分大小写的。如果没有元素匹配,将会抛出NoSuchElement异常。 ▎Webement的属性和方法: tag_name 标签名,例如‘a’表示元素 get_attribute(name) 该元素name属性的值 text 该元素内的文本,例如hello中的‘hello’ clear() 对于文本字段或文本区域元素,清除其中输入的文本 is_displayed() 如果该元素可见,返回True,否则返回False is_enabled() 对于输入元素,如果该元素启用,返回True,否则返回False is_selected() 对于复选框或单选框元素,如果该元素被选中,返回True,否则返回False location 一个字典,包含键x和y,表示该元素在页面上的位置 find_element_*和find_elements_*方法返回的WebElement对象有一个click()方法,模拟鼠标在该元素上点击。 这个方法用于链接跳转,选择单选按钮,点击提交按钮,或者触发该元素被鼠标点击时发生的任何事情。 向web页面的文本字段发送击键,只要找到那个文本字段的或 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()点击“关闭窗口”按钮。>>> import requests,bs4
>>> exampleFile=requests.get('http://www.baidu.com')
>>> exampleBS=bs4.BeautifulSoup(exampleFile.text,'html.parser')
>>> elems=exampleBS.select('a')
>>> type(elems)
[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)