技术标签: python技能树 python Python入门 精彩技术文 python技能树共建 开发语言
requests-html
模块安装使用 pip install requests-html
即可,官方手册查询地址:requests-html.kennethreitz.org/,官方并没有直接的中文翻译,在检索过程中,确实发现了一版中文手册,在文末提供。
先看一下官方对该库的基本描述:
Only Python 3.6 is supported. 仅支持 Python 3.6 ,实测发现 3.6 以上版本依旧可以。
对于该库的简单使用,代码如下所示:
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('https://python.org/')
print(r)
首先从 requests_html
库导入 HTMLSession
类,然后将其实例化之后,调用其 get
方法,发送请求,得到的 r
输出为 <Response [200]>
,后续即可使用内置的解析库对数据进行解析。
由于该库是解析 html
对象,所以可以查看对应的 html
对象包含哪些方法与与属性。
通过 dir
函数查阅。
print(dir(r.html))
# 输出如下内容:
['__aiter__', '__anext__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__',
'__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', '_async_render', '_encoding', '_html', '_lxml', '_make_absolute', '_pq', 'absolute_links', 'add_next_symbol',
'arender', 'base_url', 'default_encoding', 'element', 'encoding', 'find', 'full_text', 'html', 'links', 'lxml', 'next',
'next_symbol', 'page', 'pq', 'raw_html', 'render', 'search', 'search_all', 'session', 'skip_anchors', 'text', 'url', 'xpath']
该函数只能输入大概内容,细节还是需要通过 help 函数查询,例如:
html 对象的方法包括
find
:提供一个 css 选择器,返回一个元素列表;xpath
:提供一个 xpath 表达式,返回一个元素列表;search
: 根据传入的模板参数,查找 Element 对象;search_all
:同上,返回的全部数据;html 对象的属性包括
links
:返回页面所有链接;absolute_links
:返回页面所有链接的绝对地址;base_url
:页面的基准 URL;html
,raw_html
,text
:以 HTML 格式输入页面,输出未解析过的网页,提取页面所有文本;有了上述内容铺垫之后,在进行 Python 爬虫的编写就会变的容易许多,requests-html
库将通过 3~4 个案例进行学习掌握,接下来进入第一个案例。
本次要采集的目标网站为:www.world68.com/top.asp?t=5star&page=1
,目标站点描述为【全球名站】。
在获取数据源发送请求前,忽然想起可以动态修改 user-agent
,查阅该库源码发现,它只是使用了 fake_useragent
库来进行操作,并无太神奇的地方,所以可用可不用该内容。
DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8'
def user_agent(style=None) -> _UserAgent:
"""Returns an apparently legit user-agent, if not requested one of a specific
style. Defaults to a Chrome-style User-Agent.
"""
global useragent
if (not useragent) and style:
useragent = UserAgent()
return useragent[style] if style else DEFAULT_USER_AGENT
其余内容相对比较简单,页码规则如下:
www.world68.com/top.asp?t=5star&page=1
www.world68.com/top.asp?t=5star&page=2
累计页数直接在底部进行了展示,可以设计为用户手动输入,即 input
函数实现。
目标数据存储网站名与网站地址即可,基于此,开始编码。
首先通过单线程实现 requests-html
的基本逻辑,注意到下述代码非常轻量,
from requests_html import HTMLSession
session = HTMLSession()
page_size = int(input("请输入总页码:"))
for page in range(1, page_size + 1):
world = session.get(f'http://www.world68.com/top.asp?t=5star&page={
page}')
world.encoding = 'gb2312'
# world.html.encoding = "gb2312"
# print(world.text)
print("正在采集数据", world.url)
title_a = world.html.find('dl>dt>a')
for item in title_a:
name = item.text
url = item.attrs['href']
with open('webs.txt', "a+", encoding="utf-8") as f:
f.write(f"{
name},{
url}\n")
上述代码重点部分说明如下:
world.encoding
,设置了网页解析编码;world.html.find('dl>dt>a')
通过 css 选择器,查找所有的网页标题元素;item.text
提取网页标题内容;item.attrs['href']
获取元素属性,即网站域名。运行效果如下所示,获取到的 3519
个站点,就不在提供了,简单运行 1 分钟代码,即可得到。
由于上述代码太少了,完全不够今日代码量,我们顺手将其修改为多线程形式。
import requests_html
import threading
import time
import fcntl
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global page, lock, page_size
while True:
lock.acquire(True)
if page >= page_size:
lock.release()
break
else:
page += 1
lock.release()
requests_html.DEFAULT_ENCODING = "gb18030"
session = requests_html.HTMLSession()
print("正在采集第{}页".format(page), "*" * 50)
try:
page_url = f'http://www.world68.com/top.asp?t=5star&page={
page}'
world = session.get(page_url, timeout=10)
print("正在采集数据", world.url)
# print(world.html)
title_a = world.html.find('dl>dt>a')
print(title_a)
my_str = ""
for item in title_a:
name = item.text
url = item.attrs['href']
my_str += f"{
name.encode('utf-8').decode('utf-8')},{
url}\n"
with open('thread_webs.txt', "a+", encoding="utf-8") as f:
fcntl.flock(f.fileno(), fcntl.LOCK_EX) # 文件加锁
f.write(f"{
my_str}")
except Exception as e:
print(e, page_url)
if "__main__" == __name__:
page_size = int(input("请输入总页码:"))
page = 0
thread_list = []
# 获取开始时间
start = time.perf_counter()
lock = threading.Lock()
for i in range(1, 5):
t = MyThread()
thread_list.append(t)
for t in thread_list:
t.start()
for t in thread_list:
t.join()
# 获取时间间隔
elapsed = (time.perf_counter() - start)
print("程序运行完毕,总耗时为:", elapsed)
在正式进行编码之后,发现存在比较大的问题,编码问题,出现如下错误:
encoding error : input conversion failed due to input error, bytes 0x81 0xE3 0xD3 0xAA
encoding error : input conversion failed due to input error, bytes 0x81 0xE3 0xD3 0xAA
encoding error : input conversion failed due to input error, bytes 0x81 0xE3 0xD3 0xAA
I/O error : encoder error
该错误在执行单线程时并未发生,但是当执行多线程时,异常开始出现,本问题在互联网上无解决方案,只能自行通过 requests-html
库的源码进行修改。
打开 requests_html.py
文件,将 417 行左右的代码进行如下修改:
def __init__(self, *, session: Union['HTMLSession', 'AsyncHTMLSession'] = None, url: str = DEFAULT_URL, html: _HTML, default_encoding: str = DEFAULT_ENCODING, async_: bool = False) -> None:
# 修改本部分代码
# Convert incoming unicode HTML into bytes.
# if isinstance(html, str):
html = html.decode(DEFAULT_ENCODING,'replace')
super(HTML, self).__init__(
# Convert unicode HTML to bytes.
element=PyQuery(html)('html') or PyQuery(f'<html>{
html}</html>')('html'),
html=html,
url=url,
default_encoding=default_encoding
)
代码 if isinstance(html, str):
用于判断 html
是否为 str
,但是在实测过程中发现 html
是 <class 'bytes'>
类型,所以数据没有进行转码工作,故取消相关判断。
除此以外,通过输出 world.html.encoding
发现网页的编码不是 GB2312
,而是 gb18030
,所以通过下述代码进行了默认编码的设置。
requests_html.DEFAULT_ENCODING = "gb18030"
按照如上内容进行修改之后,代码可以正常运行,数据能正确的采集到。
本案例还新增了代码运行时长的计算,具体如下:
# 获取开始时间
start = time.perf_counter()
# 执行代码的部分
# 获取时间间隔
elapsed = (time.perf_counter() - start)
print("程序运行完毕,总耗时为:", elapsed)
完整的代码运行效果如下所示:
文章浏览阅读3.8k次,点赞7次,收藏77次。写在前面,最近收到了很多小伙伴们的建议,大屏的数据源是否可以展示更丰富的种类,比如Excel,数据库等,那就更加贴近小伙伴们的实际工作场景,可以很快在工作中应用,所以应小伙伴需求,就诞生了这篇【基于 Echarts + Python 动态实时大屏范例(DataBase数据源)- 可视大屏案例】。另外,很多实际展示场景下需要自动播放效果,本案例也展示了Events和DispatchAction触发的饼图和地图高亮效果,非常实用。之前小伙伴们建.._python mysql echarts 源代码
文章浏览阅读10w+次,点赞229次,收藏1.1k次。递归算法说简单点即就是自身程序的调用,若你掌握递归相应逻辑,递归之时你便可以起飞!!!_递归算法
文章浏览阅读1.3w次,点赞153次,收藏125次。博雯 发自 凹非寺量子位 报道 | 公众号 QbitAI一觉醒来,几个T的硬盘数据化为乌有。不说暗无天日吧,也至少是惨绝人寰了。毫不夸张的说,上周四的6月24日,西部数据硬盘的My Boo...
文章浏览阅读1.5k次。这个问题已经遇到好几次,解决起来也熟练了很多。出现这种问题一般都是html或页面中的某一内部元素宽度超了。下面总结我遇到的几种情况:1、某一内部元素width设为100%,然而它还有border的宽度,border的宽度不包含在width中,所以结果超了。2、span行内元素,由于它是行内元素,不设display:block之类,宽度设定对它没用,当初弄的时候没有意识到这个问题,结果在谷歌浏览器没..._html页面設置超出100%出現滾動條
文章浏览阅读3.3k次。【EXCEL绘制地图】获取地图图标信息时遇到问题。请确保处于联机状态,然后重试问题说明:如题,在绘制全球数据地图时报错,但是中国地图不会报错。解决方案:将excel上的office账户退出即可参考网站:为什么我的3D地图无法使用..._获取地图图表信息时遇到问题,请确保处于联机状态
文章浏览阅读1.5k次。威尔逊定理在初等数论中,威尔逊定理给出了判定一个自然数是否为素数的充分必要条件。即:当且仅当p为素数时:( p -1 )! ≡ -1 ( mod p ),但是由于阶乘是呈爆炸增长的,其结论对于实际操作意义不大。hdu5391用到了这一数论定理。Zball in Tina TownTime Limit: 3000/1500 MS (Java/Others) Me_hdu5391
文章浏览阅读1.2k次,点赞4次,收藏20次。图床 - 引用ur图片api - 调用接口和生产借口文档说明MDN - 学习前端chrome插件Octotree - github展示树Allow-Control-Allow-Origin - 跨域_网页开发常用的一些图片网站
文章浏览阅读668次。文章目录第一章零基础入门深度学习(下)加载库数据处理模型设计训练配置训练过程保存模型测试模型完整代码今天是学习这门课程的第二天,学习内容是利用飞桨的深度学习平台来进行波士顿房价的预测,至于为什么要用飞桨这个平台,以下是官方回答,我也是刚接触,之前用的都是pytorch,现在一起学习呗,再次附上脑图链接:打卡学习笔记第一章零基础入门深度学习(下)加载库#加载飞桨、Numpy和相关类库import paddleimport paddle.fluid as fluidimport paddle.f
文章浏览阅读1.5k次。转自:http://blog.csdn.net/Miracle08/article/details/1457060 最近发现Visual C++ 6.0有一个有趣的,能让programmer发疯的bug。Debug版本编译出来的程序可能最终会异常中止,也许是报告程序停在断点xxxxxxx。更确切地说是用debug 版本的运行时库编译的程序。 由于项目需要写了一个求最短路径的引__heap_alloc_dbg
文章浏览阅读7.1k次,点赞19次,收藏70次。作者 | 李秋键责编 | Carol封图 | CSDN 下载自视觉中国近几年来Python语言得到了快速发展,而Pygame作为Python开发应用和游戏必备的库更是展现了Python的..._python吃豆人实验原理
文章浏览阅读2.6k次。相信不少玩家都在游戏中会碰到登陆游戏了之后不能点PLAY,不能点商城,不能点个人资料,反正什么都点不了的问题,今天小编就给大家来解答下要怎么解决吧。LOL点了PLAY没反映要怎么解决?很多人都有出现这个问题,在进游戏之前,应该就是在输入账号密码那里吧,要不就是选择服务器哪里,有一个选项,把QT勾选上,就可以了。以上就是特玩小编为大家带来的关于lol点了play反映的解决办法了,希望对你有帮助。相信..._tgp不能用
文章浏览阅读851次。HDFS体系结构(各种进程状态)NameNode【名称节点】开启方式(关闭方式):hdfs namenode(关闭Terminal)hadoop-daemon.sh start namenode(hadoop-daemon.sh stop namenode或杀死进程)start-dfs.sh(stop-dfs.sh或杀死进程)namenode默认大小..._hdfs中包含哪些守护进程