爬虫实操1-静态网页-3个解析方式比较

以天涯论坛的简单网页爬取为例子,BeautifulSoup、PyQuery以及Xpath都使用一下。

1. 网页访问

使用requests库访问

import requests
url='http://bbs.tianya.cn/hotArticle.jsp?pn=1'  #天涯论坛
req=requests.get(url)
req

输出:
表示能够成功访问
爬虫实操1-静态网页-3个解析方式比较_第1张图片
展示下网页源代码:

print(req.text)

爬虫实操1-静态网页-3个解析方式比较_第2张图片

2. 确定想要抓取的内容

爬虫实操1-静态网页-3个解析方式比较_第3张图片
打开开发者工具,网页源代码。现在想要提取这个页面的帖子标题、帖子作者以及发布时间。
每一个帖子的三条信息都包含在 的节点里面
分别在并列的3个 标签内
节点下还包括节点

3. 定位位置,抓取信息

3.1 使用BeautifulSoup

首先解析网页:

from bs4 import BeautifulSoup
html=req.text
#html1=req.content
soup=BeautifulSoup(html,'lxml')
#soup=BeautifulSoup(html1,'html.parser')
soup

爬虫实操1-静态网页-3个解析方式比较_第4张图片
现在知道标题都在一个的节点里,可以使用find_all函数,找到所有节点,遍历选择需要的内容。
注意点: 因为是要写循环,遍历三个td节点,找td的上一个节点作为操作对象(tr节点)

选择:

#内容都在tr节点内,可以先找出所有的tr节点
contents_bs=soup.find_all('tr')

for item in contents_bs:
    #帖子标题
    try:
        title=item.find('td',attrs={
     'class':'td-title'})
        title=title.text
    except:
        title=None
    #作者
    try:
        author=item.find('a',attrs={
     'class':'author'})
        author=author.text
    except:
        author=None
    #时间
    try:
        time=item.select('tr td:nth-child(3)')  #css选择器结果是列表
        time=[i.get_text() for i in time]       
        #结果是列表,列表内一个元素,将这个元素提出来,
        #且css选择器的文本提取方式是get_text()函数
    except:
        time=None
    print(title,author,time)
    print('\n')

爬虫实操1-静态网页-3个解析方式比较_第5张图片
问题:
1 为什么要用try-except?
因为是对tr节点,选下面的td节点,但第一个是空的,None,选择文本内容时会报错,所以添加try-except,跳过出错的
爬虫实操1-静态网页-3个解析方式比较_第6张图片
2 find函数与css选择器的使用?
Beautifulsoup可以使用标准选择器(find,find_all),也可以使用css选择器,find_all函数是选择出全部符合的内容,find是选择出第一个符合条件的内容,因为这里帖子标题作者所在节点都有其各自的属性,使用find就可以定位,第一个就能够选出来。
但时间所在节点,就一个标签名td,没有能够标识的属性,就使用了css选择器,定位第三个td节点。
3 time=[i.get_text() for i in time] 的使用?
爬虫实操1-静态网页-3个解析方式比较_第7张图片
css选择器结果是列表,选出的td标签在列表中,需要先将其从列表中提出来,成为正常的网页语句,…,才能用get_text()提取文本内容。

3.2 使用PyQuery

首先解析网页:

from pyquery import PyQuery
doc=PyQuery(req.text)
print(doc)

爬虫实操1-静态网页-3个解析方式比较_第8张图片
同样的,定位节点,循环遍历

注意点: PyQuery使用**.items**将节点内容选择出来
选择:

contents_pq=doc('div tr')                   #先选节点,再用items()
for item in contents_pq.items():
    title=item('td:nth-child(1)').text()  #使用的是css选择器
    author=item('td:nth-child(2)').text()
    time=item('td:nth-child(3)').text()
    print(title,author,time)
    print('\n')

或者另一种写法

for item in doc.items('div tr'):          #doc后面跟.items()
    title=item('td:nth-child(1)').text()  #使用的是css选择器
    author=item('td:nth-child(2)').text()
    time=item('td:nth-child(3)').text()
    print(title,author,time)
    print('\n')

爬虫实操1-静态网页-3个解析方式比较_第9张图片
(这里没有报错,没有用try-except)

3.3 使用Xpath

首先解析网页:

#使用xpath
from lxml import etree
html=etree.HTML(req.text)
print(html)

输出:

注意点:
1 xpath插件很好用,结合起来会十分方便。
2 xpath的路径是链式的

选择:

title_s=html.xpath("//tbody//tr")
for item in title_s:
    #标题
    title=item.xpath("td[@class='td-title']/a/text()")
    title=''.join(title)
    #作者
    author=item.xpath("td//a[@class='author']/text()")
    author=''.join(author)
    #时间
    time=item.xpath("td[3]/text()")
    time=''.join(time)
    
    print(title,author,time)

爬虫实操1-静态网页-3个解析方式比较_第10张图片
这里xpath的使用,同样是先选择大的节点,在大节点中,遍历需要的小节点选取内容,与上面两种方式的逻辑相同,只是xpath的路径,有xpath插件的加持,个人觉得更好写!
问题:
为什么会有 ‘’.join() 语句,是因为xpath选择出来的文本内容,是在一个列表里,这个列表包含一个元素,要保存文本内容,就需要将字符串的文本内容提取出来,使用上面的函数可以实现这个效果。


以上便是三种解析器在解析天涯论坛时,不同的选取方式,针对不同的网页,还有可能碰到各种细节问题。
总的来说,个人还是倾向使用xpath,比较方便。


4. 保存抓取内容

这里使用上面的xpath语句,将内容保存到csv文件中

import csv
file='test1.csv'
csvf=open(file,'a+',encoding='utf-8',newline='')
writer=csv.writer(csvf)

writer.writerow(('标题','作者','发布时间'))

title_s=html.xpath("//tbody//tr")
for item in title_s:
    #标题
    title=item.xpath("td[@class='td-title']/a/text()")
    title=''.join(title)
    #作者
    author=item.xpath("td//a[@class='author']/text()")
    author=''.join(author)
    #时间
    time=item.xpath("td[3]/text()")
    time=''.join(time)
    
    writer.writerow((title,author,time))
csvf.close()

但文字乱码,encoding='gbk’时,会报错
" ‘gbk’ codec can’t encode character ‘\u200b’ in position 7: illegal multibyte sequence"
改成encoding=‘utf-8’,但保存下来的文件乱码(解决方式暂时是先用记事本打开,以utf-8编码另存csv文件,可以转换回来)
如何设置encoding,或者说如何解决导出数据乱码,还没有找到好的解决方式,以后解决了再更。
爬虫实操1-静态网页-3个解析方式比较_第11张图片

你可能感兴趣的:(python爬虫,爬虫)