一、简介

网络爬虫的定义:
网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟客户端发送网络请求,获取响应数据,一种按照一定的规则,自动地抓取万维网信息的程序或脚本。
网络爬虫的作用:
模拟客户端发送请求获取响应数据, 按照一定规则, 自动从万维网上获取信息的程序。
网络爬虫与浏览器的区别:
image.png
网络爬虫与浏览器的区别:
浏览器是展示数据的, 而网络爬虫是采集数据的。

Python爬虫用到的知识点:

  1. Python语法知识。
  2. 重要内置库urllib, http等,用于下载网页
  3. 正则表达式re、BeautifulSoup(bs4)、Xpath(lxml)等网页解析工具
  4. 反爬机制,header,robot,时间间隔,代理ip,隐含字段等
  5. 特殊网站的爬取,解决登录、Cookie、动态网页等问题
  6. 数据储存
  7. Python的多线程、多进程进行爬取,提高爬虫效率
  8. 爬虫的框架,Scrapy、PySpider等
  9. 分布式爬虫(数据量庞大的需求)

    二、爬虫需要的库以及解析方式

    请求-现 HTTP 请求操作

    1.urllib库

    Python有一个内置的urllib库,可谓是爬虫过程非常重要的一部分了。这个内置库的使用就可以完成向服务器发出请求并获得网页的功能。
    查看urllib库存在的方法。

    1. import urllib
    2. print(dir(urllib))
    1. ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

    image.png
    关注点:
    image.png

    Error:

    urllib举出的exception类,里面主要包括了两个重要的exception类,URLError类和HTTPError类。

    1. class URLError(OSError):
    2. # URLError is a sub-type of OSError, but it doesn't share any of
    3. # the implementation. need to override __init__ and __str__.
    4. # It sets self.args for compatibility with other EnvironmentError
    5. # subclasses, but args doesn't have the typical format with errno in
    6. # slot 0 and strerror in slot 1. This may be better than nothing.
    7. def __init__(self, reason, filename=None):
    8. self.args = reason,
    9. self.reason = reason
    10. if filename is not None:
    11. self.filename = filename
    12. def __str__(self):
    13. return '<urlopen error %s>' % self.reason
  • URLError类是OSError的子类,继承OSError,没有自己的任何行为特点,但是将作为error里面所有其它类型的基类使用。
  • URLError类初始化定义了reason参数,意味着当使用URLError类的对象时,可以查看错误的reason。

    1. class HTTPError(URLError, urllib.response.addinfourl):
    2. """Raised when HTTP error occurs, but also acts like non-error return"""
    3. __super_init = urllib.response.addinfourl.__init__
    4. def __init__(self, url, code, msg, hdrs, fp):
    5. self.code = code
    6. self.msg = msg
    7. self.hdrs = hdrs
    8. self.fp = fp
    9. self.filename = url
    10. # The addinfourl classes depend on fp being a valid file
    11. # object. In some cases, the HTTPError may not have a valid
    12. # file object. If this happens, the simplest workaround is to
    13. # not initialize the base classes.
    14. if fp is not None:
    15. self.__super_init(fp, hdrs, url, code)
    16. def __str__(self):
    17. return 'HTTP Error %s: %s' % (self.code, self.msg)
    18. def __repr__(self):
    19. return '<HTTPError %s: %r>' % (self.code, self.msg)
    20. # since URLError specifies a .reason attribute, HTTPError should also
    21. # provide this attribute. See issue13211 for discussion.
    22. @property
    23. def reason(self):
    24. return self.msg
    25. @property
    26. def headers(self):
    27. return self.hdrs
    28. @headers.setter
    29. def headers(self, headers):
    30. self.hdrs = headers
  • HTTPError是URLError的子类,当HTTP发生错误将举出HTTPError。

  • HTTPError也是HTTP有效回应的实例,因为HTTP协议错误是有效的回应,包括状态码,headers和body。所以看到在HTTPError初始化的时候定义了这些有效回应的参数。
  • 当使用HTTPError类的对象时,可以查看状态码,headers等

注意:
URLError发生时,就会返回reason,或者HTTPError发生错误时就会返回code。

request

urllib.request 定义了一些打开 URL 的函数和类,包含授权验证、重定向、浏览器 cookies等。
urllib.request 可以模拟浏览器的一个请求发起过程。
我们可以使用 urllib.request 的 urlopen 方法来打开一个 URL,语法格式如下:
如:

  1. urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
  • url:url 地址。
  • data:发送到服务器的其他数据对象,默认为 None。
  • timeout:设置访问超时时间。
  • cafile 和 capath:cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。
  • cadefault:已经被弃用。
  • context:ssl.SSLContext类型,用来指定 SSL 设置。

  1. import urllib.request
  2. response = urllib.request.urlopen('http://python.org/')
  3. #读取整个网站页面
  4. result = response.read().decode('utf-8')
  5. print(result)
  6. #读取一行
  7. print(response.readline())
  8. #读取文件的全部内容,它会把读取的内容赋值给一个列表变量。
  9. print(response.readlines())
  10. for line in response.readlines():
  11. print(line)

模拟浏览器请求头:
抓取网页一般需要对 headers(网页头信息)进行模拟,这时候需要使用到 urllib.request.Request 类。

  1. class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
  • url:url 地址。
  • data:发送到服务器的其他数据对象,默认为 None。
  • headers:HTTP 请求的头部信息,字典格式。
  • origin_req_host:请求的主机地址,IP 或域名。
  • unverifiable:很少用整个参数,用于设置网页是否需要验证,默认是False。。
  • method:请求方法, 如 GET、POST、DELETE、PUT等。

如:

  1. import urllib.request
  2. import urllib.parse
  3. url = 'https://www.baidu.com/'
  4. #头部信息
  5. header = {
  6. 'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
  7. }
  8. request = urllib.request.Request(url,headers=header)
  9. reponse = urllib.request.urlopen(request).read()
  10. print(reponse)

parse

urllib.parse 用于解析 URL

  1. urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)

urlstring 为 字符串的 url 地址,scheme 为协议类型,allow_fragments 参数为 false,则无法识别片段标识符。相反,它们被解析为路径,参数或查询组件的一部分,并 fragment 在返回值中设置为空字符串。

  1. from urllib.parse import urlparse
  2. o = urlparse("https://baidu.com")
  3. print(o)

解析结果说明:

属性 索引 值(如果不存在)
scheme 0 URL协议 scheme 参数
netloc 1 网络位置部分 空字符串
path 2 分层路径 空字符串
params 3 最后路径元素的参数 空字符串
query 4 查询组件 空字符串
fragment 5 片段识别 空字符串
username 用户名 None
password 密码 None
hostname 主机名(小写) None
port 端口号为整数(如果存在) None

robotparser

urllib.robotparser 用于解析 robots.txt 文件。
robots.txt(统一小写)是一种存放于网站根目录下的 robots 协议,它通常用于告诉搜索引擎对网站的抓取规则。
urllib.robotparser 提供了 RobotFileParser 类,语法如下:

  1. class urllib.robotparser.RobotFileParser(url='')
  • set_url(url) - 设置 robots.txt 文件的 URL。
  • read() - 读取 robots.txt URL 并将其输入解析器。
  • parse(lines) - 解析行参数。
  • can_fetch(useragent, url) - 如果允许 useragent 按照被解析 robots.txt 文件中的规则来获取 url 则返回 True。
  • mtime() -返回最近一次获取 robots.txt 文件的时间。 这适用于需要定期检查 robots.txt 文件更新情况的长时间运行的网页爬虫。
  • modified() - 将最近一次获取 robots.txt 文件的时间设置为当前时间。
  • crawl_delay(useragent) -为指定的 useragent 从 robots.txt 返回 Crawl-delay 形参。 如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。
  • request_rate(useragent) -以 named tuple RequestRate(requests, seconds) 的形式从 robots.txt 返回 Request-rate 形参的内容。 如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。
  • site_maps() - 以 list() 的形式从 robots.txt 返回 Sitemap 形参的内容。 如果此形参不存在或者此形参的 robots.txt 条目存在语法错误,则返回 None。

    1. import urllib.robotparser
    2. rp = urllib.robotparser.RobotFileParser()
    3. rp.set_url("http://www.musi-cal.com/robots.txt")
    4. rp.read()
    5. rrate = rp.request_rate("*")
    6. print(rrate)

    2.requests

    requests 是一个优雅而简单的 Python HTTP请求库。
    requests 的作用是 发送请求获取响应数据。

    1. pip install requests

    使用步骤:

    1. 导入模块.
    2. 发送get请求, 获取响应:.
    3. 从响应中获取数据. ```python

      1. 导入模块

      import requests

2. 发送请求, 获取响应

response = requests.get(‘http://www.baidu.com‘)

print(response)

3. 获取响应数据

print(response.encoding) # ISO-8859-1

response.encoding = ‘utf8’

print(response.text)

print(response.content.decode())

  1. response 常见属性<br />response.text : 响应体 str类型.<br />response.ecoding : 二进制转换字符使用的编码.<br />respones.content: 响应体 bytes类型<br />案例:丁香园疫情首
  2. ```python
  3. # 1. 导入模块
  4. import requests
  5. # 2. 发送请求, 获取响应
  6. response = requests.get('https://ncov.dxy.cn/ncovh5/view/pneumonia')
  7. # 3. 从响应中, 获取数据
  8. # print(response.text)
  9. print(response.content.decode())

3.selenium

自动化测试工具。一个调用浏览器的 driver,通过这个库你可以直接调用浏览器完成某些操作,比如输入验证码。
查看官网

4.aiohttp

基于 asyncio 实现的 HTTP 框架。异步操作借助于 async/await 关键字,使用异步库进行数据抓取,可以大大提高效率。
功能:

  • 同时支持客户端使用和服务端使用
  • 同时支持服务端WebSockets组件和客户端WebSockets组件
  • web服务器具有中间件、信号组件和可插拨路由的功能

安装:

  1. #python 3.6
  2. pip install aiohttp==1.3.3

由于上下文的缘故,请求代码必须在一个异步的函数中进行:

  1. async def fn():
  2. pass

基本语法:

  1. async with aiohttp.request('GET','https://github.com') as r:
  2. await r.text()
  1. #指定编码
  2. await resp.text(encoding='windows-1251')
  3. #适合读取图像等
  4. await resp.read()
  5. #request案例
  6. #超时处理timeout
  7. async with session.get('https://github.com', timeout=60) as r:

客户端:

  1. import aiohttp, asyncio
  2. async def main():
  3. async with aiohttp.ClientSession() as session:
  4. async with session.get('http://baidu.com') as response:
  5. print('Status:', response.status)
  6. print('Content-type:', response.headers['content-type'])
  7. html = await response.text()
  8. print(f'Body: {html[:15]}...')
  9. loop = asyncio.get_event_loop()
  10. loop.run_until_complete(main())

服务端:

  1. from aiohttp import web
  2. # 视图函数
  3. async def hello(request):
  4. name = request.match_info.get('name', 'Python')
  5. text = f'Hello, {name}'
  6. return web.Response(text=text)
  7. app = web.Application()
  8. app.router.add_get("/", hello) # 添加路由
  9. if __name__ == '__main__':
  10. web.run_app(app, host='127.0.0.1')

客户端其他使用方式

解析-从网页中提取信息

1.beautifulsoup

html 和 XML 的解析,从网页中提取信息,同时拥有强大的API和多样解析方式。
安装:

  1. # 安装 Beautiful Soup 4
  2. pip install bs4
  3. # 安装 lxml
  4. pip install lxml

BeautifulSoup对象:
代表要解析整个文档树, 它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.

  1. # 1. 导入模块
  2. from bs4 import BeautifulSoup
  3. # 2. 创建BeautifulSoup对象
  4. #指定解析器 lxml
  5. soup = BeautifulSoup('<html>data</html>', 'lxml')
  6. print(soup)

BeautifulSoup对象的find方法:

  1. find(self, name=None, attrs={}, recursive=True, text=None, **kwargs)
  2. 参数
  3. name: 标签名
  4. attrs: 属性字典
  5. recursive: 是否递归循环查找
  6. text: 根据文本内容查找
  7. 返回
  8. 查找到的第一个元素对象

如:
1.根据标签名查找: soup.find(‘a’)
2.根据属性查找: soup.find(id = ‘link1’) 或 soup.find(attrs = {‘id’: ‘link1’})
3.根据文本内容查找 : soup.find(text = ‘Elsie’ )

Tag 对象介绍:
Tag对象对应于原始文档中的XML或HTML标签Tag有很多方法和属性, 可用 遍历文档树 和 搜索文档树 以及获取标签内容
Tag 对象常见属性:
name: 获取标签名称
attrs: 获取标签所有属性的键和值
text: 获取标签的文本字符串
使用:

  1. # 1. 导入模块
  2. from bs4 import BeautifulSoup
  3. # 2. 准备文档字符串
  4. html = '''<html>
  5. <head>
  6. <title>The Dormouse's story</title>
  7. </head>
  8. <body>
  9. <p class="title">
  10. <b>The Dormouse's story</b>
  11. </p>
  12. <p class="story">Once upon a time there were three little sisters; and their names were
  13. <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
  14. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>and
  15. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  16. and they lived at the bottom of a well.
  17. </p>
  18. <p class="story">...</p>
  19. '''
  20. # 3. 创建BeautifulSoup对象
  21. soup = BeautifulSoup(html, 'lxml')
  22. # 4. 查找title标签
  23. title = soup.find('title')
  24. print(title)
  25. # 5. 查找a 标签
  26. a = soup.find('a')
  27. print(a)
  28. # 查找所有的a标签
  29. a_s = soup.find_all('a')
  30. print(a_s)
  31. # 二. 根据属性进行查找
  32. # 查找id为link1的标签
  33. # 方式1: 通过命名参数进行指定的
  34. a = soup.find(id='link1')
  35. print(a)
  36. # 方式2: 使用attrs来指定属性字典, 进行查找
  37. a = soup.find(attrs={'id': 'link1'})
  38. print(a)
  39. # 三. 根据文本内容进行查找
  40. text = soup.find(text='Elsie')
  41. print(text)
  42. # Tag对象
  43. print(type(a)) # <class 'bs4.element.Tag'>
  44. print('标签名', a.name)
  45. print('标签所有属性', a.attrs)

案例:

  1. # 1. 导入相关模块
  2. import requests
  3. from bs4 import BeautifulSoup
  4. import re
  5. import json
  6. # 2. 发送请求, 获取疫情首页内容
  7. response = requests.get('https://ncov.dxy.cn/ncovh5/view/pneumonia')
  8. home_page = response.content.decode()
  9. # print(home_page)
  10. # 3. 使用BeautifulSoup提取疫情数据
  11. soup = BeautifulSoup(home_page, 'lxml')
  12. script = soup.find(id='getListByCountryTypeService2true')
  13. text = script.text
  14. # print(text)
  15. # 4. 使用正则表达式, 提取json字符串
  16. json_str = re.findall(r'\[.+\]', text)[0]
  17. # print(json_str)
  18. # 5. 把json字符串转换为Python类型的数据
  19. last_day_corona_virus = json.loads(json_str)
  20. print(last_day_corona_virus)

中文文档

2.pyquery

jQuery 的 Python 实现,能够以 jQuery 的语法来操作解析 HTML 文档,易用性和解析速度都很好。
功能:

  • 初始化为PyQuery对象
  • 常用的CCS选择器
  • 伪类选择器
  • 查找标签
  • 获取标签信息

安装:

  1. pip install pyquery

引用方法:

  1. from pyquery import PyQuery as pq

初始化:

1.字符串初始化

  1. from pyquery import PyQuery as pq
  2. #初始化为PyQuery对象
  3. html = """
  4. <html lang="en">
  5. <head>
  6. 简单好用的
  7. <title>PyQuery</title>
  8. </head>
  9. <body>
  10. <ul id="container">
  11. <li class="object-1">Python</li>
  12. <li class="object-2">大法</li>
  13. <li class="object-3">好</li>
  14. </ul>
  15. </body>
  16. </html>
  17. """
  18. doc = pq(html)
  19. print(type(doc))
  20. print(doc)

2.html文件初始化

  1. from pyquery import PyQuery as pq
  2. #初始化为PyQuery对象
  3. test_html = pq(filename = 'test.html')
  4. print(type(test_html))
  5. print(test_html)

3.网址响应进行初始化

  1. from pyquery import PyQuery as pq
  2. #初始化为PyQuery对象
  3. response = pq(url = 'https://www.baidu.com')
  4. print(type(response))
  5. print(response)

pyquery库会默认调用urllib库,如果想使用selenium或者requests库,可以自定义PyQuery的opener参数。

  1. from pyquery import PyQuery
  2. from selenium.webdriver import PhantomJS
  3. #用selenium访问url
  4. def selenium_opener(url):
  5. driver = PhantomJS(executable_path = 'phantomjs的路径')
  6. driver.get(url)
  7. html = driver.page_source
  8. driver.quit()
  9. return html
  10. #注意,使用时opener参数是函数名,没有括号的!
  11. PyQuery(url='https://www.baidu.com/', opener=selenium_opener)

cookies、headers

  1. from pyquery import PyQuery
  2. cookies = {'Cookie':'你的cookie'}
  3. headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
  4. PyQuery(url='https://www.baidu.com/',headers=headers,cookies=cookies)

基本CSS选择器

id为container的标签

  1. from pyquery import PyQuery as pq
  2. #初始化为PyQuery对象
  3. html = """
  4. <html lang="en">
  5. <head>
  6. 简单好用的
  7. <title>PyQuery</title>
  8. </head>
  9. <body>
  10. <ul id="container">
  11. <li class="object-1">Python</li>
  12. <li class="object-2">大法</li>
  13. <li class="object-3">好</li>
  14. </ul>
  15. </body>
  16. </html>
  17. """
  18. response = pq(html)
  19. print(response('#container'))
  20. print(type(response('#container')))

class为object-1的标签

  1. from pyquery import PyQuery as pq
  2. #初始化为PyQuery对象
  3. html = """
  4. <html lang="en">
  5. <head>
  6. 简单好用的
  7. <title>PyQuery</title>
  8. </head>
  9. <body>
  10. <ul id="container">
  11. <li class="object-1">Python</li>
  12. <li class="object-2">大法</li>
  13. <li class="object-3">好</li>
  14. </ul>
  15. </body>
  16. </html>
  17. """
  18. doc = pq(html)
  19. print(doc('.object-1'))

标签名为body的标签

  1. from pyquery import PyQuery as pq
  2. #初始化为PyQuery对象
  3. html = """
  4. <html lang="en">
  5. <head>
  6. 简单好用的
  7. <title>PyQuery</title>
  8. </head>
  9. <body>
  10. <ul id="container">
  11. <li class="object-1">Python</li>
  12. <li class="object-2">大法</li>
  13. <li class="object-3">好</li>
  14. </ul>
  15. </body>
  16. </html>
  17. """
  18. doc = pq(html)
  19. print(doc('body'))

多种css选择器使用

  1. print(doc('html #container'))

伪类选择器

伪类nth

  1. print(pseudo_doc('li:nth-child(2)'))
  2. #打印第一个li标签
  3. print(pseudo_doc('li:first-child'))
  4. #打印最后一个标签
  5. print(pseudo_doc('li:last-child'))

contains

  1. #找到含有Python的li标签
  2. print(pseudo_doc("li:contains('Python')"))
  3. #找到含有好的li标签
  4. print(pseudo_doc("li:contains('好')"))

查找标签

按照条件在Pyquery对象中查找符合条件的标签,类似于BeautifulSoup中的find方法。
id=container的标签

  1. print(doc.find('#container'))

子辈标签-children方法

  1. #id=container的标签的子辈标签
  2. container = doc.find('#container')
  3. print(container.children())

父辈标签-parent方法

  1. object_2 = doc.find('.object-2')
  2. print(object_2.parent())

兄弟标签-siblings方法

  1. object_2 = doc.find('.object-2')
  2. print(object_2.siblings())

获取标签的信息

1.标签属性值的提
.attr() 传入 标签的属性名,返回属性值

  1. object_2 = doc.find('.object-2')
  2. print(object_2.attr('class'))

2.标签内的文本
.text()

  1. html_text = """
  2. <html lang="en">
  3. <head>
  4. 简单好用的
  5. <title>PyQuery</title>
  6. </head>
  7. <body>
  8. <ul id="container">
  9. Hello World!
  10. <li class="object-1">Python</li>
  11. <li class="object-2">大法</li>
  12. <li class="object-3">好</li>
  13. </ul>
  14. </body>
  15. </html>
  16. """
  17. docs = pq(html_text)
  18. print(docs.text())

tips:
如果我只想获得Hello World这个,不想得到其他的文本,可以使用remove方法将li标签去掉,然后再使用text方法

  1. container = docs.find('#container')
  2. container.remove('li')
  3. print(container.text())

3.lxml

支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高。

安装

  1. pip install lxml

官方文档:http://lxml.de/index.html

XPath语法

XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言,它最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索
XPath的选择功能十分强大,它提供了非常简明的路径选择表达式,另外,它还提供了超过100个内建函数,用于字符串、数值、时间的匹配以及节点、序列的处理等,几乎所有我们想要定位的节点,都可以用XPath来选择
官方文档
1.XPath 开发工具

  1. 开源的XPath表达式编辑工具:XMLQuire(XML格式文件可用)
  2. Chrome插件 XPath Helper
  3. Firefox插件 XPath Checker

2.Chrome中安装XPath 开发工具

  1. 1.重启浏览器,快捷键CTRL+SHIFT+X开启XPath Helper插件;
  2. 2.长按CTRL+SHIFT,鼠标指向需提取的段落,按X开启或关闭提取,提取到的段落会变为黄色。

3,选取节点
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
下面列出了最常用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

|

如:


路径表达式
结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。

4.谓词
谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

表达式 描述
[@attrib] 选取具有给定属性的所有元素
[@attrib=’value’] 选取给定属性具有给定值的所有元素
[tag] 选取所有具有指定元素的直接子节点
[tag=’text’] 选取所有具有指定元素并且文本内容是text节点

如:

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

| | //div[contains(@class,”f1”)] | 选择div属性包含”f1”的元素 |

5.选取未知节点
XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点.

如:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
html/node()/meta/@* 选择html下面任意节点下的meta节点的所有属性
//title[@*] 选取所有带有属性的 title 元素。

6.选取若干路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

7.XPath的运算符
image.png
案例:

  1. #encoding: utf-8
  2. # 导入etree时需要手动,不会有提示
  3. from lxml import etree
  4. text = """
  5. <div>
  6. <ul>
  7. <li class="aaa item-0"><a href="link1.html">第一个</a></li>
  8. <li class="bbb item-1"><a href="link2.html">second item</a></li>
  9. </ul>
  10. </div>
  11. """
  12. # 从字符串中读取
  13. def parse_text():
  14. htmlElement = etree.HTML(text)
  15. print(etree.tostring(htmlElement,encoding='utf-8').decode("utf-8"))
  16. # 从文件中读取html代码
  17. def parse_tencent_file():
  18. htmlElement = etree.parse("tencent.html")
  19. print(etree.tostring(htmlElement, encoding='utf-8').decode('utf-8'))
  20. # 解析html,指定解析器,有时候html代码不规范需要指定解析器
  21. def parse_lagou_file():
  22. # 指定解析器
  23. parser = etree.HTMLParser(encoding='utf-8')
  24. htmlElement = etree.parse("lagou.html",parser=parser)
  25. print(etree.tostring(htmlElement, encoding='utf-8').decode('utf-8'))
  26. def findText():
  27. html = etree.HTML(text, etree.HTMLParser())
  28. result = html.xpath('//li[@class="aaa"]/a/text()')
  29. result1 = html.xpath('//li[contains(@class,"aaa")]/a/text()')
  30. print(result)
  31. print(result1)
  32. if __name__ == '__main__':
  33. parse_text()
  34. findText()
  35. # parse_file()
  36. # parse_lagou_file()

lxml结合xpath
案例:
image.png

  1. #encoding: utf-8
  2. # 导入etree时需要手动,不会有提示
  3. from lxml import etree
  4. import requests
  5. def findText():
  6. # 2. 发送请求, 获取响应
  7. response = requests.get('https://www.tuliu.com/read-135151.html')
  8. response.encoding = 'utf8'
  9. html = etree.HTML(response.text, etree.HTMLParser())
  10. result = html.xpath('/html/body/div[2]/div[3]/div[1]/div[1]/div[1]/h2/text()')
  11. print(result)
  12. if __name__ == '__main__':
  13. findText()

参考

4.tesserocr

一个 OCR 库,在遇到验证码(图形验证码为主)的时候,可直接用 OCR 进行识别。
image.png
Windows 安装:
在 Windows 下,首先需要下载 tesseract,它为 tesserocr 提供了支持。
tesseract 下载地址: http://digi.bib.uni-mannheim.de/tesseract
其中文件名中带有 dev 的为开发版本,不带 dev 的为稳定版本,可以选择下载不带 dev 的版本, 例如可以选择下载 tesseract-ocr-setup-3 .05.01.exe。
下载完成后双击运行,安装程序。需要注意的是,需要句选 Additional language data(download)选项来安装 OCR 识别支持的语言包,这样 OCR 便可以识别多国语言 。
配置环境变量:
image.png
爬虫复习总结 - 图8
安装依赖:

  1. pip install tesserocr pillow

如果通过 pip 安装失败,可以尝试 Anaconda 下的 conda 来安装:

  1. conda install -c simonflueckiger tesserocr pillow

图片连接:
https://raw.githubusercontent.com/Python3WebSpider/TestTess/master/image.png

  1. import tesserocr
  2. from PIL import Image
  3. #第一种方式
  4. image = Image.open('image.png')
  5. result = tesserocr.image_to_text(image)
  6. print(result)
  7. #第二种方式
  8. print(tesserocr.file_to_text('image.png'))

存储-Python 与数据库交互

pymysql:
一个纯 Python 实现的 MySQL 客户端操作库。
pymongo:
一个用于直接连接 mongodb 数据库进行查询操作的库。
redisdump:
一个用于 redis 数据导入/导出的工具。基于 ruby 实现的,因此使用它,需要先安装 Ruby。

反爬虫机制

ip代理池,模拟user-agent,识别验证码,爬取时间控制等。
参考文档

爬虫框架

Scrapy:
很强大的爬虫框架,可以满足简单的页面爬取(比如可以明确获知url pattern的情况)。用这个框架可以轻松爬下来如亚马逊商品信息之类的数据。但是对于稍微复杂一点的页面,如 weibo 的页面信息,这个框架就满足不了需求了。
Crawley:
高速爬取对应网站的内容,支持关系和非关系数据库,数据可以导出为 JSON、XML 等。
Portia:
可视化爬取网页内容。
newspaper:
提取新闻、文章以及内容分析。
python-goose:
java 写的文章提取工具。
cola:
一个分布式爬虫框架。项目整体设计有点糟,模块间耦合度较高。