爬虫之xpath、bs4

  • 常用xpath表达式回顾
属性定位:
    #找到class属性值为song的div标签
    //div[@class="song"] 
层级&索引定位:
    #找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
    //div[@class="tang"]/ul/li[2]/a
逻辑运算:
    #找到href属性值为空且class属性值为du的a标签 //a[@href="" and @class="du"] 模糊匹配: //div[contains(@class, "ng")] //div[starts-with(@class, "ta")] 取文本: # /表示获取某个标签下的文本内容 # //表示获取某个标签下的文本内容和所有子标签下的文本内容 //div[@class="song"]/p[1]/text() //div[@class="tang"]//text() 取属性: //div[@class="tang"]//li[2]/a/@href
  • 代码中使用xpath表达式进行数据解析:
1.下载:pip install lxml
2.导包:from lxml import etree

3.将html文档或者xml文档转换成一个etree对象,然后调用对象中的方法查找指定的节点   2.1 本地文件:tree = etree.parse(文件名) tree.xpath("xpath表达式")   2.2 网络数据:tree = etree.HTML(网页内容字符串) tree.xpath("xpath表达式")
  • 安装xpath插件在浏览器中对xpath表达式进行验证:可以在插件中直接执行xpath表达式
    • 将xpath插件拖动到谷歌浏览器拓展程序(更多工具)中,安装成功

    • 启动和关闭插件 ctrl + shift + x

  • 项目需求:获取好段子中段子的内容和作者   http://www.haoduanzi.com

    from lxml import etree
    import requests
    
    url='http://www.haoduanzi.com/category-10_2.html'
    headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } url_content=requests.get(url,headers=headers).text #使用xpath对url_conten进行解析 #使用xpath解析从网络上获取的数据 tree=etree.HTML(url_content) #解析获取当页所有段子的标题 title_list=tree.xpath('//div[@class="log cate10 auth1"]/h3/a/text()') ele_div_list=tree.xpath('//div[@class="log cate10 auth1"]') text_list=[] #最终会存储12个段子的文本内容 for ele in ele_div_list: #段子的文本内容(是存放在list列表中) text_list=ele.xpath('./div[@class="cont"]//text()') #list列表中的文本内容全部提取到一个字符串中 text_str=str(text_list) #字符串形式的文本内容防止到all_text列表中 text_list.append(text_str) print(title_list) print(text_list)

用xpath爬取小说《三国演义》实例:

 1 from lxml import etree
 2 import requests
 3 
 4 url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
 5 headers = {
 6 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36",
 7 "Connection":"close"
 8 }
 9 url_content = requests.get(url=url,headers=headers).text
10 
11 tree = etree.HTML(url_content)
12 href_list = tree.xpath('//div[@class="book-mulu"]//li/a/@href')
13 new_url = 'http://www.shicimingju.com'
14 print("开始")
15 with open('./sanguo_xpath.txt','w',encoding='utf-8') as fp:
16     for href in href_list:
17         zhangjie_url = new_url + href
18         url_zhangjie = requests.get(url=zhangjie_url,headers=headers).text
19         zhangjie_tree = etree.HTML(url_zhangjie)
20         content_title = zhangjie_tree.xpath('//div[@class="www-main-container www-shadow-card "]/h1/text()')[0]
21         content = "".join(zhangjie_tree.xpath('//div[@class="chapter_content"]//text()'))
22         fp.write(content_title+"\n"+content+"\n")
23 print("结束")

【重点】

    - 问题:往往在进行大量请求发送的时候,经常会报出这一样的一个错误:HTTPConnectionPool(host:XX)Max retries exceeded with url。

    - 原因:

        1.每次数据传输前客户端要和服务器建立TCP连接,为节省传输消耗,默认为keep-alive,即连接一次,传输多次。然而如果连接迟迟不断开的话,则连接池满后则无法产生新的链接对象,导致请求无法发送。

        2.ip被封

        3.请求频率太频繁

    - 解决:如果下列解决未生效,则可以尝试再次执行程序

        1.设置请求头中的Connection的值为close,表示每次请求成功后断开连接

        2.更换请求ip

        3.每次请求之间使用sleep进行等待间隔

import requests
from fake_useragent import UserAgent
from lxml import etree import random import time url = 'http://sc.chinaz.com/jianli/free_%d.html' ua = UserAgent(verify_ssl=False,use_cache_server=False).random headers = { 'User-Agent':ua, #保证http请求成功后,立即断开连接,以解决HTTPConnectionPool(host:XX)Max retries exceeded with url的问题 'Connection': 'close', #该行不写,则会报错 } #proxy_list = ['101.255.56.201:36501','39.137.69.10:8080','195.29.106.178:58292','120.76.77.152:9999','178.75.1.111:50411','78.156.225.170:41258','193.192.177.196:56480'] for pageNum in range(1,3): get_url = format(url%pageNum) if pageNum==1: get_url = 'http://sc.chinaz.com/jianli/free.html' response = requests.get(url=get_url,headers=headers) response.encoding = 'utf-8'#处理中文乱码问题 page_text = response.text tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') for div in div_list: second_url = div.xpath('./a/@href')[0] name = div.xpath('./p/a/text()')[0]+'.rar' second_page_text = requests.get(url=second_url,headers=headers).text second_tree = etree.HTML(second_page_text) download_url_list = second_tree.xpath('//div[@class="clearfix mt20 downlist"]/ul/li/a/@href') download_url = random.choice(download_url_list) data = requests.get(url=download_url,headers=headers).content with open(name,'wb') as fp: fp.write(data) print('下载完毕===>'+name) #解决HTTPConnectionPool(host:XX)Max retries exceeded with url的问题: #time.sleep(3) #延长请求时间,模拟浏览器,否则请求频率太快会请求失败 #使用代理池 #设置请求头信息中的Connection为close


.BeautifulSoup解析

  • 环境安装
- 需要将pip源设置为国内源,阿里源、豆瓣源、网易源等
   - windows
    (1)打开文件资源管理器(文件夹地址栏中)
    (2)地址栏上面输入 %appdata%
    (3)在这里面新建一个文件夹  pip
    (4)在pip文件夹里面新建一个文件叫做  pip.ini ,内容写如下即可
        [global] timeout = 6000 index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com - linux (1)cd ~ (2)mkdir ~/.pip (3)vi ~/.pip/pip.conf (4)编辑内容,和windows一模一样 - 需要安装:pip install bs4 bs4在使用时候需要一个第三方库,把这个库也安装一下 pip install lxml
  • 基础使用
使用流程:       
    - 导包:from bs4 import BeautifulSoup
    - 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容
        (1)转化本地文件:
             - soup = BeautifulSoup(open('本地文件'), 'lxml') (2)转化网络文件: - soup = BeautifulSoup('字符串类型或者字节类型', 'lxml') (3)打印soup对象显示内容为html文件中的内容 基础巩固: (1)根据标签名查找 - soup.a 只能找到第一个符合要求的标签 (2)获取属性 - soup.a.attrs 获取a所有的属性和属性值,返回一个字典 - soup.a.attrs['href'] 获取href属性 - soup.a['href'] 也可简写为这种形式 (3)获取内容 - soup.a.string - soup.a.text - soup.a.get_text() 【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容 (4)find:找到第一个符合要求的标签 - soup.find('a') 找到第一个符合要求的 - soup.find('a', title="xxx") - soup.find('a', alt="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (5)find_all:找到所有符合要求的标签 - soup.find_all('a') - soup.find_all(['a','b']) 找到所有的a和b标签 - soup.find_all('a', limit=2) 限制前两个 (6)根据选择器选择指定的内容 select:soup.select('#feng') - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器 - 层级选择器: div .dudu #lala .meme .xixi 下面好多级 div > p > a > .lala 只能是下面一级 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象

用bs4爬取《三国演义》代码:

 1 from bs4 import BeautifulSoup
 2 import  requests
 3 
 4 headers = {
 5 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36",
 6 "Connection":"close"
 7 }
 8 url = "http://www.shicimingju.com/book/sanguoyanyi.html"
 9 
10 def get_content(content_url):
11     new_url= "http://www.shicimingju.com"
12     get_cont_url = new_url + content_url
13     print(get_cont_url)
14     res = requests.get(url=get_cont_url,headers=headers).text
15     new_bs4_obj = BeautifulSoup(res,'lxml')
16     ele = new_bs4_obj.find('div',class_='chapter_content')
17     content = ele.text
18     return content
19 
20 response = requests.get(url=url, headers=headers)
21 res_text = response.text
22 bs4_obj = BeautifulSoup(res_text,'lxml')
23 a_elements = bs4_obj.select('.book-mulu > ul > li > a')
24 print(a_elements)
25 with open('./sanguo_bs4.txt','w',encoding='utf-8') as fp:
26     print("开始")
27     for a_element in a_elements:
28         title = a_element.text
29         content_url = a_element['href']
30         print(title)
31         print(content_url)
32         content = get_content(content_url)
33         fp.write(title + "\n" + content +"\n")
34 print("结束")

  

猜你喜欢

转载自www.cnblogs.com/zhaosijia/p/10133880.html