奥门威尼斯网址Python基于队列的多线程爬虫

by admin on 2019年9月3日

python四线程多队列(BeautifulSoup互连网爬虫)

程序差非常少内容如下:

程序中装置多个系列分别为queue担负贮存网站,out_queue担任存放网页的源代码。

ThreadUrl线程担负将队列queue中网站的源代码urlopen,存放到out_queue队列中。

DatamineThread线程负担运用BeautifulSoup模块从out_queue网页的源代码中领收取想要的内容并出口。

这只是二个核心的框架,可以依赖要求延续扩大。

次第中有很详细的笺注,如有有失水准跪求指正啊。

 

import Queue
import threading
import urllib2
import time
from BeautifulSoup import BeautifulSoup

hosts = ["http://yahoo.com","http://taobao.com","http://apple.com",
         "http://ibm.com","http://www.amazon.cn"]

queue = Queue.Queue()#存放网址的队列
out_queue = Queue.Queue()#存放网址页面的队列

class ThreadUrl(threading.Thread):
    def __init__(self,queue,out_queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.out_queue = out_queue

    def run(self):
        while True:
            host = self.queue.get()
            url = urllib2.urlopen(host)
            chunk = url.read()
            self.out_queue.put(chunk)#将hosts中的页面传给out_queue
            self.queue.task_done()#传入一个相当于完成一个任务

class DatamineThread(threading.Thread):
    def __init__(self,out_queue):
        threading.Thread.__init__(self)
        self.out_queue = out_queue

    def run(self):
        while True:
            chunk = self.out_queue.get()
            soup = BeautifulSoup(chunk)#从源代码中搜索title标签的内容
            print soup.findAll(['title'])
            self.out_queue.task_done()

start = time.time()
def main():
    for i in range(5):
        t = ThreadUrl(queue,out_queue)#线程任务就是将网址的源代码存放到out_queue队列中
        t.setDaemon(True)#设置为守护线程
        t.start()

    #将网址都存放到queue队列中
    for host in hosts:
        queue.put(host)

    for i in range(5):
        dt = DatamineThread(out_queue)#线程任务就是从源代码中解析出

 

奥门威尼斯网址
程序差不离内容如下:
程序中装置七个种类分别为queue担负寄存网站,out_queue担负存放网页的源代…

python爬虫之BeautifulSoup

python爬虫之BeautifulSoup

0. 前言

Wpsec-H4rdy
http://www.h4rdy.me/post/1cba6492\_6b61da3

Wpsec-p0di
http://zone.wooyun.org/content/11888

简介

Beautiful Soup提供一些简练的、python式的函数用来拍卖导航、寻觅、修改剖析树等职能。它是三个工具箱,通过深入分析文书档案为客商提供应和须要要抓取的多少,因为轻便,所以没有供给多少代码就足以写出三个整机的应用程序。Beautiful Soup电动将输入文书档案转变为Unicode编码,输出文书档案调换为utf-8编码。你无需考虑编码情势,除非文书档案未有一点点名四个编码情势,那时,Beautiful Soup就不可能自动识别编码情势了。然后,你唯有须要证圣元(Synutra)下原始编码情势就足以了。
Beautiful Soup已改成和lxmlhtml6lib同一精彩的python解释器,为客户灵活地提供分化的分析攻略或强劲的进程。

简介

Beautiful Soup提供部分简练的、python式的函数用来拍卖导航、寻觅、修改分析树等职能。它是叁个工具箱,通过深入分析文书档案为客商提供需求抓取的数据,因为轻便,所以不供给多少代码就足以写出一个整机的应用程序。Beautiful Soup电动将输入文书档案转变为Unicode编码,输出文书档案转变为utf-8编码。你不要求记挂编码格局,除非文书档案未有点名二个编码方式,那时,Beautiful Soup就不可能自动识别编码格局了。然后,你偏偏须要验证一下原始编码方式就足以了。
Beautiful Soup已改成和lxmlhtml6lib未有差距于美好的python解释器,为顾客灵活地提供不一致的剖析计策或强劲的进程。

在介绍BeautifulSoup模块前,
大家先剖析一下我们要爬取的网页结构是如何的。经常网页都包括层叠样式表(斯洛伐克语全称:Cascading
Style Sheets),比方。
推荐应用Google浏览器仍然火狐浏览器方便急速查看网页结构。譬喻在chrome中国百货企业度首页右击,选拔’inspect’,就能够查看到网页结构,以及各样标签层级关系。

#!/usr/bin/python
# -*- coding: utf-8 -*-
#author:Erie

import re
import sys
import requests
import Queue
import threading
from bs4 import BeautifulSoup
from urlparse import urljoin
from urlparse import urlparse
from urlparse import urlunparse
from posixpath import normpath

reload(sys)
sys.setdefaultencoding('utf-8')
sys.setdefaultencoding('gbk')

VisitedUrl = Queue.Queue()
VisitedLinks = []

#Spider Function()
class Spider(threading.Thread):
    def __init__ (self,queue,links):
        threading.Thread.__init__(self)
        tmp = urlparse(links)
        self.queue = queue
        self.host = tmp.netloc
        self.pro = tmp.scheme
        self.path = tmp.path

    #chongzu Url
    def myjoin (self,base, url):
        url1 = urljoin(base, url)
        arr = urlparse(url1)
        path = normpath(arr[2])
        return urlunparse((arr.scheme, arr.netloc, path, arr.params, arr.query, arr.fragment))
    def getpage (self,url):
        Response = requests.get(url)
        try:
            Htmlpage = Response.content
            soup = BeautifulSoup(Htmlpage)
            all_href = soup.findAll("a")
            for href in all_href:
                tmp = str(href)
                if tmp.find('href') != -1:
                    if href['href'].find("http://") != -1:
                        if urlparse(href['href']).hostname==self.host:
                            UnvisitedHref = href['href']
                            if UnvisitedHref not in VisitedLinks:
                                self.queue.put(UnvisitedHref)
                    else:
                        UnvisitedHref = self.myjoin(url,href['href'])
                        if UnvisitedHref not in VisitedLinks and urlparse(UnvisitedHref).hostname==self.host  and (urlparse(UnvisitedHref).path.count('/')-self.path.count('/'))<=3 and UnvisitedHref.find('#') == -1 and UnvisitedHref.find('.js' )== -1 and UnvisitedHref.find('.jpg') == -1 and UnvisitedHref.find('bmp') == -1 and UnvisitedHref.find('.png') == -1 and UnvisitedHref.find('.gif') == -1:
                            self.queue.put(UnvisitedHref)
        except :
            pass

    def run (self):
        while True:
            Urling =self.queue.get()
            print Urling
            VisitedLinks.append(Urling)
            self.getpage(Urling)
            self.queue.task_done()
#main Function()
def main(Url):    
    #Url = sys.argv[1]
    for i in range(5):
        spider = Spider(VisitedUrl,Url)
        spider.start()
    VisitedUrl.put(Url)
    VisitedUrl.join()
if __name__ == "__main__":
    main('http://www.sta.edu.cn')

安装

  • pip install BeautifulSoup4
  • easy_install BeautifulSoup4

安装

  • pip install BeautifulSoup4
  • easy_install BeautifulSoup4

奥门威尼斯网址 1

创建BeautifulSoup对象

  • 首先应当导入BeautifulSoup类库 from bs4 import BeautifulSoup

  • 上面起先创立对像,在初步以前为了便利演示,先创制一个html文本,如下:

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
  • 创制对象:soup=BeautifulSoup(html,'lxml'),这里的lxml是深入分析的类库,前段时间来讲个人认为最棒的分析器了,平素在用那些,安装方式:pip install lxml

创建BeautifulSoup对象

  • 首先应当导入BeautifulSoup类库 from bs4 import BeautifulSoup

  • 上面伊始成立对像,在始发在此之前为了便利演示,先成立二个html文本,如下:

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
  • 成立对象:soup=BeautifulSoup(html,'lxml'),这里的lxml是解析的类库,近日来讲个人以为最棒的分析器了,平素在用这一个,安装格局:pip install lxml

image

Tag

Tag就是html中的一个标签,用BeautifulSoup就能够深入分析出来Tag的具体内容,具体的格式为soup.name,其中namehtml下的竹签,具体实举个例子下:

  • print soup.title输出title标签下的剧情,包罗此标签,这些将会输出<title>The Dormouse's story</title>

  • print soup.head

Tag

Tag就是html中的贰个标签,用BeautifulSoup就会解析出来Tag的具体内容,具体的格式为soup.name,其中namehtml下的价签,具体实例如下:

  • print soup.title输出title标签下的内容,富含此标签,那一个将会输出<title>The Dormouse's story</title>

  • print soup.head

1. 创办爬虫爬取网页

注意:

此处的格式只好得到这么些标签的首先个,前面会讲到获取多少个标签的办法。个中对于Tag有四个着重的质量nameattrs,分别表示名字和天性,介绍如下:

  • name:对于Tag,它的name就是其自己,如soup.p.name就是p

  • attrs是一个字典类型的,对应的是性质-值,如print soup.p.attrs,输出的正是{'class': ['title'], 'name': 'dromouse'},当然你也能够获得切实的值,如print soup.p.attrs['class'],输出的正是[title]是三个列表的品种,因为贰性情能只怕对应三个值,当然你也得以通过get方法获得属性的,如:print soup.p.get('class')。还足以一向利用print soup.p['class']

注意:

此间的格式只能得到这么些标签的第二个,后边会讲到获取八个标签的不二诀窍。个中对于Tag有三个第一的个性nameattrs,分别表示名字和性质,介绍如下:

  • name:对于Tag,它的name正是其本人,如soup.p.name就是p

  • attrs是多个字典类型的,对应的是性质-值,如print soup.p.attrs,输出的就是{'class': ['title'], 'name': 'dromouse'},当然你也足以收获具体的值,如print soup.p.attrs['class'],输出的正是[title]是贰个列表的花色,因为壹本质量可能对应多少个值,当然你也足以通过get方法获得属性的,如:print soup.p.get('class')。还足以平昔使用print soup.p['class']

爬取网址:url
=www.pythonscraping.com/pages/warandpeace.html

get

get艺术用于获取标签下的属性值,注意那是三个最主要的秘技,在非常多场子都能用到,比如你要猎取<img src="#">标签下的图像url,那么就足以用soup.img.get('src'),具体剖判如下:

    print soup.p.get("class")   #得到第一个p标签下的src属性

get

get措施用于获取标签下的属性值,注意那是一个关键的法门,在无数场合都能用到,譬如您要博得![](#)标签下的图像url,那么就能够用soup.img.get('src'),具体深入分析如下:

    print soup.p.get("class")   #得到第一个p标签下的src属性

网页如图所示,有浅绛红和清水蓝字体。在蔚蓝字体处右键选用“inspect”深入分析标签结构可见。浅莲红字体均隐含在标签GreenText在这之中。

string

赢得标签下的文书内容,只有在此标签下未有子标签,只怕唯有一个子标签的图景下才干回到个中的内容,不然再次来到的是None切实实比如下:

    print soup.p.string #在上面的一段文本中p标签没有子标签,因此能够正确返回文本的内容

    print soup.html.string  #这里得到的就是None,因为这里的html中有很多的子标签

string

收获标签下的文本内容,唯有在此标签下未有子标签,大概唯有贰个子标签的意况下工夫重临在那之中的开始和结果,不然重返的是None现实实举例下:

    print soup.p.string #在上面的一段文本中p标签没有子标签,因此能够正确返回文本的内容

    print soup.html.string  #这里得到的就是None,因为这里的html中有很多的子标签

奥门威尼斯网址 2

get_text()

能够获得多个标签中的全体文件内容,包蕴子孙节点的内容,那是最常用的艺术

get_text()

能够收获三个标签中的全部文件内容,富含子孙节点的原委,那是最常用的法子

image

探究文书档案树

搜寻文书档案树

1.1 抓取网页

find_all( name , attrs , recursive , text , **kwargs )

find_all是用于找出节点中具有符合过滤条件的节点

1.name参数:是Tag的名字,如p,div,title …..

  • soup.find_all("p")
    查找全体的p标签,再次回到的是[<b>The Dormouse's story</b>],能够透过遍历获取每贰个节点,如下:
    ps=soup.find_all("p")
    for p in ps:
        print p.get('class')   #得到p标签下的class属性
  • 传播正则表明式:soup.find_all(re.compile(r'^b')查找以b始发的全体标签,这里的bodyb标签都会被查到

  • 盛传类列表:如若传入列表参数,BeautifulSoup会将与列表中任一成分特别的剧情再次来到.上面代码找到文档中负有<a>标签和<b>标签

soup.find_all(["a", "b"])   

2.KeyWords参数,正是传播属性和对应的属性值,只怕部分任何的表明式

  • soup.find_all(id='link2'),这么些将会招来找到全数的id属性为link2的价签。传入正则表明式soup.find_all(href=re.compile("elsie")),那么些将会招来全体href品质满足正则表达式的竹签
  • 流传多少个值:soup.find_all(id='link2',class_='title')
    ,那些将会查找到况兼知足这两特性格的竹签,这里的class必须用class_盛传参数,因为classpython中的关键词

  • 稍稍属性不能够因此上述措施直接寻觅,例如html5中的data-*属性,但是能够透过attrs参数内定一个字典参数来寻觅包罗特殊质量的竹签,如下:

# [<div data-foo="value">foo!</div>]
data_soup.find_all(attrs={"data-foo": "value"})   #注意这里的atts不仅能够搜索特殊属性,亦可以搜索普通属性

soup.find_all("p",attrs={'class':'title','id':'value'})  #相当与soup.find_all('p',class_='title',id='value')

3.text参数:通过 text 参数能够搜搜文书档案中的字符串内容.与 name
参数的可选值同样, text 参数接受 字符串 , 正则宣布式 , 列表, True

soup.find_all(text="Elsie")
# [u'Elsie']

soup.find_all(text=["Tillie", "Elsie", "Lacie"])
# [u'Elsie', u'Lacie', u'Tillie']

soup.find_all(text=re.compile("Dormouse"))
[u"The Dormouse's story", u"The Dormouse's story"]

4.limit参数:find_all()
方法重回全体的研究结构,假使文书档案树异常的大那么寻找会异常慢.借使大家无需方方面面结果,能够动用
limit
参数限制重返结果的数量.效果与SQL中的limit珍视字类似,当搜索到的结果数量达到
limit 的界定时,就告一段落找出再次回到结果.

文书档案树中有3tag顺应查找条件,但结果只回去了2个,因为大家限制了回去数量,代码如下:

soup.find_all("a", limit=2)
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

5.recursive 参数:调用tagfind_all()
方法时,BeautifulSoup会寻觅当前tag的全体子孙节点,如若只想搜寻tag的间接子节点,可以行使参数
recursive=False

find_all( name , attrs , recursive , text , **kwargs )

find_all是用来寻觅节点中享有符合过滤条件的节点

  1. name参数:是Tag的名字,如p,div,title …..
  • soup.find_all("p")
    查找全数的p标签,重回的是[<b>The Dormouse's story</b>],能够透过遍历获取每一个节点,如下:
    ps=soup.find_all("p")
    for p in ps:
        print p.get('class')   #得到p标签下的class属性
  • 传播正则表明式:soup.find_all(re.compile(r'^b')查找以b开头的具有标签,这里的bodyb标签都会被查到

  • 盛传类列表:假使传入列表参数,BeautifulSoup会将与列表中任一成分极其的源委重返.上边代码找到文书档案中有着<a>标签和<b>标签

soup.find_all(["a", "b"])   
  1. KeyWords参数,正是传播属性和呼应的属性值,可能某个任何的表明式
  • soup.find_all(id='link2'),那些将会招来找到全体的id属性为link2的竹签。传入正则表明式soup.find_all(href=re.compile("elsie")),那个将会招来全体href脾气满意正则表明式的价签
  • 流传多少个值:soup.find_all(id='link2',class_='title')
    ,这一个将会查找到而且满足那五个属性的标签,这里的class必须用class_盛传参数,因为classpython中的关键词

  • 稍稍属性无法因而上述措施直接寻觅,举个例子html5中的data-*品质,可是能够透过attrs参数钦点三个字典参数来寻觅满含特殊性质的标签,如下:

# [<div data-foo="value">foo!</div>]
data_soup.find_all(attrs={"data-foo": "value"})   #注意这里的atts不仅能够搜索特殊属性,亦可以搜索普通属性

soup.find_all("p",attrs={'class':'title','id':'value'})  #相当与soup.find_all('p',class_='title',id='value')
  1. text参数:通过 text 参数能够搜搜文书档案中的字符串内容.与 name
    参数的可选值同样, text 参数接受 字符串 , 正则表达式 , 列表,
    True
soup.find_all(text="Elsie")
# [u'Elsie']

soup.find_all(text=["Tillie", "Elsie", "Lacie"])
# [u'Elsie', u'Lacie', u'Tillie']

soup.find_all(text=re.compile("Dormouse"))
[u"The Dormouse's story", u"The Dormouse's story"]
  1. limit参数:find_all()
    方法重回全体的寻觅结构,假诺文书档案树相当的大那么寻找会非常慢.要是大家无需任何结出,可以采用
    limit
    参数限制再次来到结果的数量.效果与SQL中的limit主要字类似,当找出到的结果数量达到
    limit 的范围时,就停下搜索重返结果.

文档树中有3tag符合查找条件,但结果只回去了2个,因为我们限制了回到数量,代码如下:

soup.find_all("a", limit=2)
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
  1. recursive 参数:调用tagfind_all()
    方法时,BeautifulSoup会招来当前tag的持有子孙节点,假使只想搜寻tag的直接子节点,能够行使参数
    recursive=False
from urllib.request import urlopen

from bs4 import BeautifulSoup

url ='http://www.pythonscraping.com/pages/warandpeace.html'

html= urlopen(url) #抓取了该url网页

soup = BeautifulSoup(html) #使用BeautifulSoup对网页进行解析

name_list = soup.find_all("span",{'class': 'green'})#find_all抓取所有绿色字体,返回list

for name in name_list:

    print(name.get_text()) #get_text()函数剔除字符串中所有tag符号只保留tag中包含的文本

find( name , attrs , recursive , text , **kwargs )

它与 find_all() 方法独一的界别是 find_all()
方法的回到结果是值包涵多少个元素的列表,而 find()
方法直接重临结果,正是间接重临第一相配到的要素,不是列表,不用遍历,如soup.find("p").get("class")

find( name , attrs , recursive , text , **kwargs )

它与 find_all() 方法独一的分别是 find_all()
方法的归来结果是值富含一个要素的列表,而 find()
方法直接再次回到结果,正是直接再次来到第一相称到的元素,不是列表,不用遍历,如soup.find("p").get("class")

2. find() 和 find_all()

推介有手艺的诸位查看BeautifulSoup官方文书档案,这里大概讲明一下。
请看之下相比:

  find_all(tag, attributes, recursive, text,limit, keywords)
# find_all(标签, 属性, 递归, 文本,限制查询数量, 关键字)
  find(tag,attributes, recursive, text,keywords)
#find 相当于find_all(,limit=1)

非常多的状态咱们只会蒙受前四个参数,tag和attributes。tag和attributes都得以找出多个值。

from urllib.request import urlopen

from bs4 import BeautifulSoup

url ='http://www.pythonscraping.com/pages/warandpeace.html'

html= urlopen(url) #抓取了该url网页

soup = BeautifulSoup(html) #使用BeautifulSoup对网页进行解析

hs = soup.find_all({'h1', 'h2'})#find_all抓取所有绿色字体,返回list

print(hs)

获得结果:

[<h1>War and Peace</h1>, <h2>Chapter 1</h2>]

同理,属性参数也能够包涵两个属性。比如需求寻找全数浅莲红和深桔黄的文本:

....
words = soup.find_all('span', {'class':{'green', 'red'}})
print(len(words))

有野趣的相爱的人能够看看红色和辛丑革命的tag分别有些许个。

根本字参数能够用来选用包涵特定属性的是标签,比如:

all_text = soup.find_all(id = 'text')
print(all_text[0].get_text()

精心的爱侣或许会注意到,其实重要字参数相配完全能够用属性参数替换。

soup.find_all(id='text')
soup.find_all("",{"id":"text"})
soup.find_all(class="green")
soup.find_all('',{'class':'green'})

注意: 在BeautifulSoup4版本中find_all 和findAll
是同样的。find_all是新本子的写法,findAll是旧版本的写法,可是当前相互在本子4中通用。

css选择器

咱俩在写 CSS
时,标具名不加任何修饰,类名前加点,id名前加#,在这里我们也得以行使类似的秘技来筛选成分,用到的秘技是
soup.select(),再次来到类型是 list

css选择器

小编们在写 CSS
时,标签字不加任何修饰,类名前加点,id名前加#,在这里大家也足以使用类似的主意来筛选元素,用到的秘籍是
soup.select(),重临类型是 list

3. 1子节点和子孙节点

soup.body.h1# 选中body 标签下的h1,这个h1 标签是body标签的子节点

同理,soup.div.find_all(‘img’)会找到全数div里面包车型地铁img标签。
.children 和.descendants
相比较代码如下:

html = urlopen('http://www.pythonscraping.com/pages/page3.html')
soup = BeautifulSoup(html, 'lxml')
children = soup.find('table',{'id':'giftList'}).children
descendants = soup.find('table',{'id':'giftList'}).descendants
sum = 0
for child in children:
    print(child)
    sum +=1
print(sum)
sum2 = 0
for descendant in descendants:
    sum2+=1
    print(descendant)
print(sum2)

运作结果可见 sum = 13, sum2 = 86
取descendants的第一部分作相比较能够窥见

<tr><th>#=============<tr>是soup.find('table',{'id':'giftList'})的子节点====
Item Title
</th><th>
Description
</th><th>
Cost
</th><th>
Image
</th></tr>#============<tr>是soup.find('table',{'id':'giftList'})的子节点====
<th>        #============<th>是<tr>的子节点,('table',{'id':'giftList'})的子孙节点==
Item Title
</th>       #============<th>是<tr>的子节点,('table',{'id':'giftList'})的子孙节点==

Item Title#=========文本是<th>标签的内容,也是子孙节点================

<th>#============同上====================
Description
</th>

Description

<th>
Cost
</th>

Cost
....

相比较能够,children只列出了<tr>标签所包括的源委。而descendants列出了具备包罗的标签节点以及文本,即<tr>子标签中的装有子子孙孙标签都会寻觅重返。

经过标签字查找

print soup.select('title') 
#[<title>The Dormouse's story</title>]


print soup.select('a')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

因而标签字查找

print soup.select('title') 
#[<title>The Dormouse's story</title>]


print soup.select('a')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

3.2 父节点

常备景况下大家更平日查找子节点,而在有个别特定情景下会用到查询父节点,.parents
和 .parent。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen('http://www.pythonscraping.com/pages/warandpeace.html')
soup = BeautifulSoup(html)
print(soup.find('img', {'src':'../img/gifts/img1.jpg'}).parent.previous_sibling.get_text())

浅析一下代码是什么样行事的。

<tr>
--<td>
--<td>(3)
    --"$15.00"(4)
--s<td>(2)
    --<img src="../img/gifts/img1.jpg">(1)

1.率先定位到含src=”../img/gifts/img1.jpg”的竹签img。
2.选中img标签的父节点s<td>.
3.选中s<td>的上二个同层级标签<td>
4.选拔<td>标签中的文字

4. 拍卖同辈节点和父辈节点
BeautifulSoup的next_siblings()函数极度适用于表格查找,越发是包括标题的表格。

奥门威尼斯网址 3

image.png

from urllib.request import urlopen
from bs4 import BeautifulSoup


html = urlopen("http://www.pythonscraping.com/pages/page3.html")
soup = BeautifulSoup(html, 'lxml')

siblings = soup.find("table",{'id':'giftList'}).tr.next_siblings
sum = 0
for sibling in siblings:
    print(sibling)
    sum+=1
print(sum)

结果为:

<tr class="gift" id="gift1"><td>
Vegetable Basket
</td><td>
This vegetable basket is the perfect gift for your health conscious (or overweight) friends!
Now with super-colorful bell peppers!
</td><td>
$15.00
</td><td>
<img src="../img/gifts/img1.jpg"/>
</td></tr>


<tr class="gift" id="gift2"><td>
Russian Nesting Dolls
</td><td>
Hand-painted by trained monkeys, these exquisite dolls are priceless! And by "priceless," we mean "extremely expensive"! 8 entire dolls per set! Octuple the presents!
</td><td>
$10,000.52
</td><td>
<img src="../img/gifts/img2.jpg"/>
</td></tr>

...

11
0
[Finished in 2.2s]

代码输出产品表中的持有成品,除了首行题目。因为:
1.
搜寻对象自己不是团结的同辈,因而使用sibling相关函数时搜索对象都会被跳过。
2.代码使用的是next siblings,因而会重临寻觅对象的下贰个(些)同辈节点。

补充:除了next_siblings,记住previous_siblings常常用来探究已知最终一行轻易定位且没有供给抓取的场地。当然,next_sibling
和 previous_sibling 能够用来查找一个同辈节点。

透过类名查找

print soup.select('.sister')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过类名查找

print soup.select('.sister')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过id名查找

print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

通过id名查找

print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

组成查找

学过css的都通晓css选择器,如p #link1是查找p标签下的id属性为link1的标签

print soup.select('p #link1')    #查找p标签中内容为id属性为link1的标签
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

print soup.select("head > title")   #直接查找子标签
#[<title>The Dormouse's story</title>]  

组合查找

学过css的都知晓css选择器,如p #link1是查找p标签下的id属性为link1的标签

print soup.select('p #link1')    #查找p标签中内容为id属性为link1的标签
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

print soup.select("head > title")   #直接查找子标签
#[<title>The Dormouse's story</title>]  

质量查找

追寻时仍是能够进入属性成分,属性须求用中括号括起来,注意属性和标签属于同一节点,所以中级不可能加空格,不然会无法合作到。

print soup.select('a[class="sister"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]


print soup.select('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

同样,属性如故可以与上述查找方法组成,不在同一节点的空格隔开分离,同一节点的不加空格,代码如下:

print soup.select('p a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

以上的 select 方法重回的结果都以列表情势,能够遍历格局出口,然后用
get_text() 方法来获得它的内容

soup = BeautifulSoup(html, 'lxml')
print type(soup.select('title'))
print soup.select('title')[0].get_text()

for title in soup.select('title'):
    print title.get_text()

属性查找

追寻时还足以步向属性成分,属性要求用中括号括起来,注意属性和标签属于同一节点,所以中间不可能加空格,否则会无法同盟到。

print soup.select('a[class="sister"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]


print soup.select('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

毫无二致,属性依旧能够与上述查找方法结合,不在同一节点的空格隔断,同一节点的不加空格,代码如下:

print soup.select('p a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

以上的 select 方法重返的结果都以列表情势,能够遍历格局出口,然后用
get_text() 方法来获得它的剧情

soup = BeautifulSoup(html, 'lxml')
print type(soup.select('title'))
print soup.select('title')[0].get_text()

for title in soup.select('title'):
    print title.get_text()

修改文档树

Beautiful Soup的血性是文书档案树的搜寻,但与此同不平日间也得以平价的修改文档树,那么些虽说对于一些任何的爬虫并不适用,因为他们都是爬小说的内容的,并无需网页的源码何况修改它们,可是在自家一而再更新的稿子中有用python制作pdf电子书的,这几个就须求用到修改文档树的职能了,详细情况请见自身博客

越来越多小说请移步本身博客

修改tag的名目和属性

html="""
<p><a href='#'>修改文档树</a></p>
"""
soup=BeautifulSoup(html,'lxml')
tag=soup.a    #得到标签a,可以使用print tag.name输出标签
tag['class']='content'    #修改标签a的属性class和div
tag['div']='nav'

修改.string

留意这里假诺标签的中还嵌套了子孙标签,那么只要直白动用string那几个属性会将这里的有所的儿孙标签都覆盖掉

html="""
<p><a href='#'>修改文档树</a></p>
"""
soup=BeautifulSoup(html,'lxml')
tag=soup.a
tag.string='陈加兵的博客'   #这里会将修改文档树变成修改的内容
print  tag

soup.p.string='陈加兵的博客'   #这里修改了p标签的内容,那么就会覆盖掉a标签,直接变成的修改后的文本

print soup

append

append的诀窍的效率是在在原来标签文本前面附Gavin本,就好像python中列表的append方法

html="""
<p><a href='#'>修改文档树</a></p>
"""
soup=BeautifulSoup(html,'lxml')

soup.a.append("陈加兵的博客")    #在a标签和面添加文本,这里的文本内容将会变成修改文档树陈加兵的博客
print soup
print soup.a.contents    #这里输出a标签的内容,这里的必定是一个带有两个元素的列表

注意这里的append方法也能够将二个新的价签插入到文本的末尾,上边将会讲到

new_tag

相信学过js的朋友都晓得什么成立三个新的价签,这里的艺术和js中的大同小异,使用的new_tag

html="""
<p><p>
"""
soup=BeautifulSoup(html,'lxml')
tag=soup.p
new_tag=soup.new_tag('a')    #创建一个新的标签a
new_tag['href']='#'    #添加属性
new_tag.string='陈加兵的博客'  #添加文本
print new_tag      
tag.append(new_tag)    #将新添加的标签写入到p标签中
print tag

insert

Tag.insert() 方法与 Tag.append()
方法类似,分歧是不会把新因素加多到父节点 .contents
属性的末尾,而是把成分插入到内定的地方.与Python列表总的 .insert()
方法的用法下同:

html="""
<p><p>
"""
soup=BeautifulSoup(html,'lxml')
tag=soup.p
new_tag=soup.new_tag('a')
new_tag['href']='#'
new_tag.string='陈加兵的博客'
tag.append("欢迎来到")  #这里向p标签中插入文本,这个文本在contents下的序号为0
tag.insert(1,new_tag)   #在contents序号为1的位置插入新的标签,如果这里修改成0,那么将会出现a标签将会出现在欢饮来到的前面
print tag

只顾那的1是标签的内容在contents中的序号,能够用print tag.contents翻看当前的剧情

insert_before() 和 insert_after()

insert_before() 方法在时下tag或文本节点前插入内容,insert_after()
方法在前段时间tag或文本节点后插入内容:

soup = BeautifulSoup("<b>stop</b>")
tag = soup.new_tag("i")
tag.string = "Don't"
soup.b.string.insert_before(tag)
soup.b
# <b><i>Don't</i>stop</b>


soup.b.i.insert_after(soup.new_string(" ever "))
soup.b
# <b><i>Don't</i> ever stop</b>
soup.b.contents
# [<i>Don't</i>, u' ever ', u'stop']

clear

clear用来移除当前节点的具有的剧情,包罗内部的子孙节点和文件内容

html="""
<p><p>
"""
soup=BeautifulSoup(html,'lxml')
tag=soup.p
new_tag=soup.new_tag('a')
new_tag['href']='#'
new_tag.string='陈加兵的博客'
tag.append("欢迎来到")
tag.insert(1,new_tag)
tag.clear()    #这里将会移除所有内容
print tag

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图