Python解析网页的几种其他好方法

Python解析网页的几种其他好方法

除了使用Requests + BeautifulSoup包。
以及BeautifulSoup.find()这种比较万能的方法来匹配html的元素以外,在解析匹配网页中还存在几种比较常见并且有效的方法。
这些方法包括使用lxml,pyquery,或使用Beautiful或者Scrapy中自带的css选择器。本文中会详细介绍三种做法。

  1. lxml解析法
  2. PyQuery解析法
  3. Soup.Select方法
LXML法
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
import requests
from lxml import etree

如果使用使用lxml解析网站的话,最常用的方法是etree.HTML(),以及etree.parse()两个方法。
etree.HTML()解析一串字符,而etree.parse()解析一个html文件。
解析完后也能达到BeautifulSoup一样的效果,得到一串HTML的text文本。

user_agent= "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
headers={"User-Agent":user_agent}
url_name = "https://www.baidu.com"

html_r = requests.get(url_name,headers = headers)
html = etree.HTML(html_r.text)
result = etree.tostring(html,pretty_print = True)
print(result[0:100]) #得到的一串html的text文本
b'<html>\n<head>\n    \n    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>\n    <meta'

解析一段html的text的话,如下一例所示:

from lxml import etree
text = '''
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
'''
html = etree.HTML(text)
result = etree.tostring(html)
print(result)
b'<html><body><div>\n    <ul>\n         <li class="item-0"><a href="link1.html">first item</a></li>\n         <li class="item-1"><a href="link2.html">second item</a></li>\n         <li class="item-inactive"><a href="link3.html">third item</a></li>\n         <li class="item-1"><a href="link4.html">fourth item</a></li>\n         <li class="item-0"><a href="link5.html">fifth item</a></li>\n     </ul>\n </div>\n</body></html>'

解析一个文件的话

etree.parse("test.html")
<lxml.etree._ElementTree at 0x2d32ba1df48>

要是使用lxml来提取元素,则常用xpath来提取。
所以lxml最好的搭档是xpath。

from lxml import etree
from lxml import html
import requests

text = '''
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
</body>
</html>
'''
html_text = etree.HTML(text)
li_list = html_text.xpath('/html/body/div/ul/li/a')
for item in li_list:
    print(item.text)
first item
second item
third item
fourth item
fifth item

若以豆瓣举例

from lxml import html
import requests

page = requests.get("https://movie.douban.com/subject/4920389/")
tree = html.fromstring(page.text)
html_s = tree.xpath('//*[@id="info"]')
for item in (html_s[0]):
    if item.text != None:
        print(item.text)
类型:
动作
科幻
冒险
官方网站:
readyplayeronemovie.com
制片国家/地区:
语言:
上映日期:
2018-03-30(中国大陆)
2018-03-11(西南偏南电影节)
2018-03-29(美国)
片长:
140分钟
又名:
IMDb链接:
tt1677720

在Scrapy中,则使用response.xpath()方法加快匹配html节点的效率
如下例子所示

'''
for info in response.xpath('//div[@class="item"]'):
      item = Movie250Item()
      item['rank'] = info.xpath('div[@class="pic"]/em/text()').extract()
      item['title'] = info.xpath('div[@class="pic"]/a/img/@alt').extract()
      item['link'] = info.xpath('div[@class="pic"]/a/@href').extract()
      item['star'] = info.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/em/text()').extract()
      item['rate'] = info.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/text()').extract()
      item['quote'] = info.xpath('div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span/text()').extract()
      yield item
'''
'\nfor info in response.xpath(\'//div[@class="item"]\'):\n      item = Movie250Item()\n      item[\'rank\'] = info.xpath(\'div[@class="pic"]/em/text()\').extract()\n      item[\'title\'] = info.xpath(\'div[@class="pic"]/a/img/@alt\').extract()\n      item[\'link\'] = info.xpath(\'div[@class="pic"]/a/@href\').extract()\n      item[\'star\'] = info.xpath(\'div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/em/text()\').extract()\n      item[\'rate\'] = info.xpath(\'div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/text()\').extract()\n      item[\'quote\'] = info.xpath(\'div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span/text()\').extract()\n      yield item\n'

PyQuery法

PyQuery最厉害的地方,是能够将html的节点操作代码逻辑,在Python上如同Javascript的方法实现出来。
如PyQuery解析的方法十分简单,直接使用PyQuery([url,html.text,filename])方法即可实现。
PyQuery跟CSS选择器是比较配的,解析完网站后直接使用CSS选择器提取。

from pyquery import PyQuery as pq
doc = pq("<html></html>")
doc_baidu = pq("http://www.baidu.com")
doc_file = pq(filename = "test.html")

若下例匹配豆瓣以后,使用css选择器,则可以用很短的代码,将上文Xpath的内容匹配出来。

from pyquery import PyQuery as pd
from lxml import etree

doc = pq("<html></html>")
doc_douban = pq("https://movie.douban.com/subject/4920389/")

info = doc_douban("div #info")
print(info.text())
导演: 史蒂文·斯皮尔伯格
编剧: 扎克·佩恩 / 恩斯特·克莱恩
主演: 泰伊·谢里丹 / 奥利维亚·库克 / 本·门德尔森 / 马克·里朗斯 / 丽娜·维特 / 森崎温 / 赵家正 / 西蒙·佩吉 / T·J·米勒 / 汉娜·乔恩-卡门 / 拉尔夫·尹爱森 / 苏珊·林奇 / 克莱尔·希金斯 / 劳伦斯·斯佩尔曼 / 佩蒂塔·维克斯 / 艾萨克·安德鲁斯
类型: 动作 / 科幻 / 冒险
官方网站: readyplayeronemovie.com
制片国家/地区: 美国
语言: 英语
上映日期: 2018-03-30(中国大陆) / 2018-03-11(西南偏南电影节) / 2018-03-29(美国)
片长: 140分钟
又名: 玩家一号 / 挑战者1号(港) / 一级玩家(台) / 一号玩家
IMDb链接: tt1677720
More_Comments = doc_douban("div #hot-comments > a")
Long_Comments = doc_douban("#topic-items > div > div:nth-child(3) > div.posts > span > a")

#topic-items > div
#hot-comments > a
print(More_Comments)
print(Long_Comments)
<a href="comments?sort=new_score&amp;status=P">更多短评122443条</a>

在Scrapy中,通常也用response.css()方法来提取,如下例

'''
def parse(self, response):
    for quote in response.css('div.item'):
        yield {
            "电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
            "评分":quote.css('div.info div.bd div.star span.rating_num::text').extract(),
            "引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
        }
'''
'\ndef parse(self, response):\n    for quote in response.css(\'div.item\'):\n        yield {\n            "电影名": quote.css(\'div.info div.hd a span.title::text\').extract_first(),\n            "评分":quote.css(\'div.info div.bd div.star span.rating_num::text\').extract(),\n            "引言": quote.css(\'div.info div.bd p.quote span.inq::text\').extract()\n        }\n'

BeautifulSoup.select()方法

这种方法类似上种,是使用BeautifulSoup中的CSS选择器来提取,如下简单例子所示。

html_soup = BeautifulSoup(html_r.text,'lxml')
html_soup_li = html_soup.select("li")
print(html_soup_li)
[<li><a href="javascript:;" name="ime_hw">手写</a></li>, <li><a href="javascript:;" name="ime_py">拼音</a></li>, <li class="ln"></li>, <li><a href="javascript:;" name="ime_cl">关闭</a></li>]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容