在使用Python本爬虫采集数据时,一个很重要的操做就是如何从请求到的网页中提取数据,而正肯定位想要的数据又是第一步操做。css
本文将对比几种 Python 爬虫中比较经常使用的定位网页元素的方式供你们学习
1.传统 BeautifulSoup 操做
2.基于 BeautifulSoup 的 CSS 选择器(与 PyQuery 相似)
3.XPath
4.正则表达式html
参考网页是当当网图书畅销总榜:python
http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1
咱们以获取第一页 20 本书的书名为例。先肯定网站没有设置反爬措施,是否能直接返回待解析的内容:正则表达式
import requests url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text print(response)
仔细检查后发现须要的数据都在返回内容中,说明不须要特别考虑反爬举措浏览器
审查网页元素后能够发现,书目信息都包含在 li 中,从属于 class 为 bang_list clearfix bang_list_mode 的 ul 中ruby
进一步审查也能够发现书名在的相应位置,这是多种解析方法的重要基础学习
经典的 BeautifulSoup 方法借助 from bs4 import BeautifulSoup,而后经过 soup = BeautifulSoup(html, "lxml") 将文本转换为特定规范的结构,利用 find 系列方法进行解析,代码以下:网站
import requests from bs4 import BeautifulSoup url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text def bs_for_parse(response): soup = BeautifulSoup(response, "lxml") li_list = soup.find('ul', class_='bang_list clearfix bang_list_mode').find_all('li') # 锁定ul后获取20个li for li in li_list: title = li.find('div', class_='name').find('a')['title'] # 逐个解析获取书名 print(title) if __name__ == '__main__': bs_for_parse(response)
成功获取了 20 个书名,有些书面显得冗长能够经过正则或者其余字符串方法处理,本文不做详细介绍url
这种方法实际上就是 PyQuery 中 CSS 选择器在其余模块的迁移使用,用法是相似的。关于 CSS 选择器详细语法能够参考:http://www.w3school.com.cn/cssref/css_selectors.asp因为是基于 BeautifulSoup 因此导入的模块以及文本结构转换都是一致的:spa
import requests from bs4 import BeautifulSoup url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text def css_for_parse(response): soup = BeautifulSoup(response, "lxml") print(soup) if __name__ == '__main__': css_for_parse(response)
而后就是经过 soup.select 辅以特定的 CSS 语法获取特定内容,基础依旧是对元素的认真审查分析:
import requests from bs4 import BeautifulSoup from lxml import html url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text def css_for_parse(response): soup = BeautifulSoup(response, "lxml") li_list = soup.select('ul.bang_list.clearfix.bang_list_mode > li') for li in li_list: title = li.select('div.name > a')[0]['title'] print(title) if __name__ == '__main__': css_for_parse(response)
XPath 即为 XML 路径语言,它是一种用来肯定 XML 文档中某部分位置的计算机语言,若是使用 Chrome 浏览器建议安装 XPath Helper 插件,会大大提升写 XPath 的效率。
以前的爬虫文章基本都是基于 XPath,你们相对比较熟悉所以代码直接给出:
import requests from lxml import html url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text def xpath_for_parse(response): selector = html.fromstring(response) books = selector.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li") for book in books: title = book.xpath('div[@class="name"]/a/@title')[0] print(title) if __name__ == '__main__': xpath_for_parse(response)
若是对 HTML 语言不熟悉,那么以前的几种解析方法都会比较吃力。这里也提供一种万能解析大法:正则表达式,只须要关注文本自己有什么特殊构造文法,便可用特定规则获取相应内容。依赖的模块是 re
首先从新观察直接返回的内容中,须要的文字先后有什么特殊:
import requests import re url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text print(response)
观察几个数目相信就有答案了:<div class="name"><a href="http://product.dangdang.com/xxxxxxxx.html" target="_blank" title="xxxxxxx"> 书名就藏在上面的字符串中,蕴含的网址连接中末尾的数字会随着书名而改变。
分析到这里正则表达式就能够写出来了:
import requests import re url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text def re_for_parse(response): reg = '<div class="name"><a href="http://product.dangdang.com/\d+.html" target="_blank" title="(.*?)">' for title in re.findall(reg, response): print(title) if __name__ == '__main__': re_for_parse(response)
能够发现正则写法是最简单的,可是须要对于正则规则很是熟练。所谓正则大法好!
固然,不论哪一种方法都有它所适用的场景,在真实操做中咱们也须要在分析网页结构来判断如何高效的定位元素,最后附上本文介绍的四种方法的完整代码,你们能够自行操做一下来加深体会
import requests from bs4 import BeautifulSoup from lxml import html import re url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24hours-0-0-1-1' response = requests.get(url).text def bs_for_parse(response): soup = BeautifulSoup(response, "lxml") li_list = soup.find('ul', class_='bang_list clearfix bang_list_mode').find_all('li') for li in li_list: title = li.find('div', class_='name').find('a')['title'] print(title) def css_for_parse(response): soup = BeautifulSoup(response, "lxml") li_list = soup.select('ul.bang_list.clearfix.bang_list_mode > li') for li in li_list: title = li.select('div.name > a')[0]['title'] print(title) def xpath_for_parse(response): selector = html.fromstring(response) books = selector.xpath("//ul[@class='bang_list clearfix bang_list_mode']/li") for book in books: title = book.xpath('div[@class="name"]/a/@title')[0] print(title) def re_for_parse(response): reg = '<div class="name"><a href="http://product.dangdang.com/\d+.html" target="_blank" title="(.*?)">' for title in re.findall(reg, response): print(title) if __name__ == '__main__': # bs_for_parse(response) # css_for_parse(response) # xpath_for_parse(response) re_for_parse(response)