背景
昨天看了一篇获取房价的文章后,运行了案例代码,能看懂,但对 html 解析的用法还不熟悉。今天继续练习 Python 编码,目标网站是腾讯动漫,先完成基本信息的获取。
【某平台怎么都通不过审核,于是决定换个平台发该文】
页面元素分析
开发者模式,定位到一个节点:
根据
class 信息查询动漫节点,目标是具有ret-search-item clearfix 的 li 元素。
动漫的各项信息定位:
- 海报地址:第一个
a标签下的img标签的data-original属性。 - 动漫名称:第一个
a标签的titile属性。 - 作者:具有
ret-works-author类属性的p标签的文本。 - 描述:具有
ret-works-decs 类属性的p` 标签的文本。 - 动漫详情地址:具有
ret-works-view类属性的a标签的href属性。
编码实现
要取全部页面,考虑用多线程协作。
from bs4 import BeautifulSoup
import numpy as np
import requests
from requests.exceptions import RequestException
import threading
"--动漫网页方法--"
def spiderPage(url, page):
try:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3947.100 Safari/537.36"}
html1 = requests.request("GET", url, headers=headers, timeout=10)
html1.encoding = 'utf-8' # 加编码,重要!转换为字符串编码,read()得到的是byte格式的
html = html1.text
# print('scrawl result')
# print(html)
return html
except RequestException: # 异常捕获
print('第{0}读取网页失败'.format(page))
return None
"--解析列表页面的动漫信息--"
def parsePage(url, page):
# 取页面
html = spiderPage(url, page)
html = str(html)
if html is not None:
# soup = BeautifulSoup(html, 'lxml')
soup = BeautifulSoup(html, 'html.parser')
"--先确定动漫信息,即li标签列表,li class = ret-search-item clearfix --"
cosmics = soup.find_all("li",class_="ret-search-item clearfix")
for j in range(len(cosmics)): # 遍历每一个动漫
cosmic = cosmics[j]
"动漫海报:mod-cover-list-thumb mod-cover-effect ui-db"
poster = cosmic.findNext("a")
posterImgTag = poster.findNext("img")
posterImgUrl = posterImgTag.get("data-original")
print("posterImgUrl ",posterImgUrl)
"动漫详情 URL"
cosmicTag= cosmic.findNext("a",class_="ret-works-view")
cosmicUrl = "https://ac.qq.com/"+ cosmicTag.get("href")
"动漫名称:ret-works-title "
print("name is", poster.get("title"))
"动漫作者:ret-works-author"
author = cosmic.findNext("p",class_="ret-works-author")
print("author is ", author.text)
"动漫描述:ret-works-decs"
desc = cosmic.findNext("p",class_="ret-works-decs")
print("desc is ",desc.text)
print()
# 多线程爬虫
for i in range(1,100,2): # 遍历网页1-101
url1 = "https://ac.qq.com/Comic/index/page/" + str(i)
url2 = "https://ac.qq.com/Comic/index/page/" + str(i + 1)
t1 = threading.Thread(target=parsePage, args=(url1, i)) # 线程1
t2 = threading.Thread(target=parsePage, args=(url2, i + 1)) # 线程2
t1.start()
t2.start()
运行结果
编码启示录
首先,有个大疑惑就是解析文本的时候, soup = BeautifulSoup(html, 'html.parser') 和 soup = BeautifulSoup(html, 'lxml') 有什么区别呢?
最初参考房价项目的代码,用的是 lxml ,select 按 class 解析不到东西,再改成 html.parser 用 find 方法可以正常解析了。
答案是,解析器不同:
- html.parser,内置,不需要额外的依赖项。
- html5lib,最宽大,如果HTML损坏,最好使用它。
- lxml,最快,依赖外部 C 。
其次,Python 解析页面还是挺好定位的。