<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>BeautifulSoup on cnDenis的笔记</title><link>https://blog.cndenis.com/tags/BeautifulSoup.html</link><description>Recent content in BeautifulSoup on cnDenis的笔记</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 12 Dec 2012 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.cndenis.com/tags/BeautifulSoup/index.xml" rel="self" type="application/rss+xml"/><item><title>用Python解析HTML，BeautifulSoup使用简介</title><link>https://blog.cndenis.com/Python/2012/12/%E7%94%A8Python%E8%A7%A3%E6%9E%90HTMLBeautifulSoup%E4%BD%BF%E7%94%A8%E7%AE%80%E4%BB%8B.html</link><pubDate>Wed, 12 Dec 2012 00:00:00 +0000</pubDate><guid>https://blog.cndenis.com/Python/2012/12/%E7%94%A8Python%E8%A7%A3%E6%9E%90HTMLBeautifulSoup%E4%BD%BF%E7%94%A8%E7%AE%80%E4%BB%8B.html</guid><description>&lt;p&gt;Beautiful Soup是一个用于解析HTML文件的Python库，这里介绍一下它的基本使用方法。&lt;/p&gt;
&lt;p&gt;Beautiful Soup字面意思是美好的汤，主页在 &lt;a class="link" href="http://www.crummy.com/software/BeautifulSoup/" target="_blank" rel="noopener"
 &gt;http://www.crummy.com/software/BeautifulSoup/&lt;/a&gt;，
下载与安装无需啰嗦，假设你已经装好了，现在开始吧。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;##装汤——Making the Soup&lt;/p&gt;
&lt;p&gt;首先要把待解析的HTML装入BeautifulSoup。BeautifulSoup可以接受文件句柄或是字符串作为输入：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;soup1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;soup2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;lt;html&amp;gt;data&amp;lt;/html&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;##汤料——Soup中的对象&lt;/p&gt;
&lt;h3 id="标签tag"&gt;标签（Tag）
&lt;/h3&gt;&lt;p&gt;标签对应于HTML元素，也就是应于一对HTML标签以及括起来的内容（包括内层标签和文本），如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;b class=&amp;#34;boldest&amp;#34;&amp;gt;Extremely bold&amp;lt;/b&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;soup.b就是一个标签，soup其实也可以视为是一个标签，其实整个HTML就是由一层套一层的标签组成的。&lt;/p&gt;
&lt;h3 id="名字name"&gt;名字（Name）
&lt;/h3&gt;&lt;p&gt;名字对应于HTML标签中的名字（也就是尖括号里的第一项）。每个标签都具有名字，标签的名字使用&lt;code&gt;.name&lt;/code&gt;来访问，例如上例中，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[document]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="属性atrriutes"&gt;属性（Atrriutes）
&lt;/h3&gt;&lt;p&gt;属性对应于HTML标签中的属性部分（也就是尖括号里带等号的那些）。标签可以有许多属性，也可以没有属性。属性使用类似于字典的形式访问，用方括号加属性名，例如上例中，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;boldest&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以使用.attrs直接获得这个字典，例如，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;boldest&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="文本text"&gt;文本（Text）
&lt;/h3&gt;&lt;p&gt;文本对应于HTML中的文本（也就是尖括号外的部分）。文件使用&lt;code&gt;.text&lt;/code&gt;来访问，例如上例中，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Extremely bold&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;##找汤料——Soup中的查找&lt;/p&gt;
&lt;p&gt;解析一个HTML通常是为了找到感兴趣的部分，并提取出来。BeautifulSoup提供了&lt;code&gt;find&lt;/code&gt;和&lt;code&gt;find_all&lt;/code&gt;的方法进行查找。&lt;code&gt;find&lt;/code&gt;只返回找到的第一个标签，而&lt;code&gt;find_all&lt;/code&gt;则返回一个列表。因为查找用得很多，所以BeautifulSoup做了一些很方便的简化的使用方式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#等价于 tag(&amp;#34;a&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#等价于 tag.a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;因为找不到的话，find_all返回空列表，&lt;code&gt;find&lt;/code&gt;返回&lt;code&gt;None&lt;/code&gt;，而不会抛出异常，所以，也不用担心 &lt;code&gt;tag(&amp;quot;a&amp;quot;)&lt;/code&gt; 或 &lt;code&gt;tag.a&lt;/code&gt; 会因为找不到而报错。限于python的语法对变量名的规定，&lt;code&gt;tag.a&lt;/code&gt; 的形式只能是按名字查找，因为点号.后面只能接变量名，而带括号的形式 &lt;code&gt;tag()&lt;/code&gt; 或 &lt;code&gt;tag.find()&lt;/code&gt; 则可用于以下的各种查找方式。&lt;/p&gt;
&lt;p&gt;查找可以使用多种方式：字符串、列表、键-值（字典）、正则表达式、函数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;字符串： 字符串会匹配标签的名字，例如 &lt;code&gt;tag.a&lt;/code&gt; 或 &lt;code&gt;tag(&amp;quot;a&amp;quot;)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;列表： 可以按一个字符串列表查找，返回名字匹配&lt;em&gt;任意&lt;/em&gt;一个字符串的标签。例如 &lt;code&gt;tag(&amp;quot;h2&amp;quot;, &amp;quot;p&amp;quot;)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;键-值： 可以用&lt;code&gt;tag(key=value)&lt;/code&gt;的形式，来按标签的属性查找。键-值查找里有比较多的小花招，这里列几条：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;class
&lt;code&gt;class&lt;/code&gt;是Python的保留字，不能当变量名用，偏偏在HTML中会有很多 &lt;code&gt;class=XXX&lt;/code&gt; 的情况，BeautifulSoup的解决方法是加一下划线，用 &lt;code&gt;class_&lt;/code&gt; 代替,如 &lt;code&gt;tag(class_=XXX)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;True
当值为True时，会匹配所有带这个键的标签，如 &lt;code&gt;tag(href=True)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;text
text做为键时表示查找按标签中的文本查找，如 &lt;code&gt;tag(text=something）&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;正则表达式： 例如 &lt;code&gt;tag(href=re.compile(&amp;quot;elsie&amp;quot;))&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;函数： 当以上方法都行不通时，函数是终极方法。写一个以单个标签为参数的函数，传入 &lt;code&gt;find&lt;/code&gt; 或 &lt;code&gt;find_all&lt;/code&gt; 进行查找。如&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;class&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 会返回所有带class属性但不带id属性的标签&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;##再来一碗——按文档的结构查找&lt;/p&gt;
&lt;p&gt;HTML可以解析成一棵标签树，因此也可以按标签在树中的相互关系来查找。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;查找上层节点：&lt;code&gt;find_parents()&lt;/code&gt; 和 &lt;code&gt;find_parent()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查找下一个兄弟节点：&lt;code&gt;find_next_siblings()&lt;/code&gt; 和 &lt;code&gt;find_next_sibling()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查找上一个兄弟节点：&lt;code&gt;find_previous_siblings()&lt;/code&gt; 和 &lt;code&gt;find_previous_sibling()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上四个都只会查同一父节点下的兄弟&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;查找下层节点：其实上面说的find和find_all就是干这活的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查找下一个节点（无视父子兄弟关系） &lt;code&gt;find_all_next()&lt;/code&gt; 和 &lt;code&gt;find_next()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查找上一个节点（无视父子兄弟关系） &lt;code&gt;find_all_previous()&lt;/code&gt; 和 &lt;code&gt;find_previous()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上的这些查找的参都和&lt;code&gt;find&lt;/code&gt;一样，可以搭配着用。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;##看颜色选汤——按CSS查找&lt;/p&gt;
&lt;p&gt;用 &lt;code&gt;.select()&lt;/code&gt;方法，看 &lt;a class="link" href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#css-selectors" target="_blank" rel="noopener"
 &gt;http://www.crummy.com/software/BeautifulSoup/bs4/doc/#css-selectors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;##一些小花招&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;BeautifulSoup 可以支持多种解析器，如lxml, html5lib, html.parser. 如：&lt;code&gt;BeautifulSoup(&amp;quot;&amp;lt;a&amp;gt;&amp;lt;/b&amp;gt;&amp;quot;, &amp;quot;html.parser&amp;quot;)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BeautifulSoup 用于解析xml的话，目前只支持lxml，需要自己另行安装。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;具体表现可参考 &lt;a class="link" href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#differences-between-parsers" target="_blank" rel="noopener"
 &gt;http://www.crummy.com/software/BeautifulSoup/bs4/doc/#differences-between-parsers&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;BeautifulSoup 在解析之前会先把文本转换成unicode。BeautifulSoup会优先考虑使用页面的charset定义。如果遇上网页的charset定义与实际使用的不符，就可能会产年乱码。可以用 &lt;code&gt;from_encoding&lt;/code&gt; 指定编码，如：&lt;code&gt; BeautifulSoup(markup, from_encoding=&amp;quot;gb18030&amp;quot;)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soup.prettify()可以输出排列得很好看的HTML文本，遇上中文的话可以指定编码使其显示正常，如 &lt;code&gt;soup.prettify(&amp;quot;gbk&amp;quot;)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>