背景
昨天看了一篇获取 House Price 的文章后,运行了案例代码,能看懂,但对 html 解析的用法还不熟悉。
今天继续练习 Python 编码,目标是腾讯 Cosmic ,先完成基本信息的获取。为什么选这个呢,主要是昨天想对着某文章练习 Python Code of Spider 时,发现它是一个付费专栏,于是自己来写写。
页面元素分析
开发者模式,定位到一个节点,根据 class
信息查询 Cosmic 节点,目标是具有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' # 加编码html = html1.text# print('scrawl result')# print(html)return htmlexcept 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-101url1 = "https://ac.qq.com/Comic/index/page/" + str(i)url2 = "https://ac.qq.com/Comic/index/page/" + str(i + 1)thread1 = threading.Thread(target=parsePage, args=(url1, i)) thread2 = threading.Thread(target=parsePage, args=(url2, i + 1))thread1.start()thread2.start()
运行结果
编码启示录
首先,有个大疑惑就是解析文本的时候, soup = BeautifulSoup(html, 'html.parser')
和 soup = BeautifulSoup(html, 'lxml')
有什么区别呢?
最初参考的代码,用的是 lxml
,select
按 class
解析不到东西,再改成 html.parser
用 find
方法可以正常解析了。
答案是,解析器不同:
- html.parser,内置,不需要额外的依赖项。
- html5lib,最宽大,如果HTML损坏,最好使用它。
- lxml,最快,依赖外部 C 。
其次,Python 解析页面还是挺好定位的。
今天先完成基础信息的获取,下一步的完善目标是生成 DataFrame
数据,写入 Excel 表格,同时获取全部的动漫图片。