分类目录归档:Python 爬虫

推荐一款小众且好用的 Python 爬虫库—RoboBrowser

1. 前言

今天推荐一款小众轻量级的爬虫库:RoboBrowser

RoboBrowser,Your friendly neighborhood web scraper!由纯 Python 编写,运行无需独立的浏览器,它不仅可以做爬虫,还可以实现 Web 端的自动化

项目地址:

https://github.com/jmcarp/robobrowser

2. 安装及用法

在实战之前,我们先安装依赖库及解析器

PS:官方推荐的解析器是 「lxml」

# 安装依赖
pip3 install robobrowser

# lxml解析器(官方推荐)
pip3 install lxml

RoboBrowser 常见的 2 个功能为:

  • 模拟表单 Form 提交

  • 网页数据爬取

使用 RoboBrowser 进行网页数据爬取,常见的 3 个方法如下:

  • find

    查询当前页面满足条件的第一个元素

  • find_all

    查询当前页面拥有共同属性的一个列表元素

  • select

    通过 CSS 选择器,查询页面,返回一个元素列表

需要指出的是,RoboBrowser 依赖于 BS4,所以它的使用方法和 BS4 类似

更多功能可以参考:

https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

3. 实战一下

我们以「 百度搜索及爬取搜索结果列表 」为例

3-1  打开目标网站

首先,我们实例化一个 RoboBrowser 对象

from time import sleep

from robobrowser import RoboBrowser

home_url = 'https://baidu.com'

#  parser: 解析器,HTML parser; used by BeautifulSoup
#  官方推荐:lxml
rb = RoboBrowser(history=True, parser='lxml')

# 打开目标网站
rb.open(home_url)

然后,使用 RoboBrowser 实例对象中的 open() 方法打开目标网站

3-2  自动化表单提交

首先,使用 RoboBrowser 实例对象获取网页中的表单 Form

然后,通过为表单中的输入框赋值模拟输入操作

最后,使用 submit_form() 方法进行表单提交,模拟一次搜索操作

# 获取表单对象
bd_form = rb.get_form()

print(bd_form)

bd_form['wd'].value = "AirPython"

# 提交表单,模拟一次搜索
rb.submit_form(bd_form)

3-3  数据爬取

分析搜索页面的网页结构,利用 RoboBrowser 中的 select() 方法匹配出所有的搜索列表元素

遍历搜索列表元素,使用 find() 方法查询出每一项的标题及 href 链接地址

# 查看结果
result_elements = rb.select(".result")

# 搜索结果
search_result = []

# 第一项的链接地址
first_href = ''

for index, element in enumerate(result_elements):
    title = element.find("a").text
    href = element.find("a")['href']
    search_result.append(title)

    if index == 0:
        first_href = element.find("a")
        print('第一项地址为:', href)

print(search_result)

最后,使用 RoboBrowser 中的 follow_link() 方法模拟一下「点击链接,查看网页详情」的操作

# 跳转到第一个链接
rb.follow_link(first_href)

# 获取历史
print(rb.url)

需要注意的是,follow_link() 方法的参数为带有 href 值的 a 标签

4. 最后

文中结合百度搜索实例,使用 RoboBrowser 完成了一次自动化及爬虫操作

相比 Selenium、Helium 等,RoboBrowser 更轻量级,不依赖独立的浏览器驱动

如果想处理一些简单的爬虫或 Web 自动化,RoboBrowser 完全够用;但是面对一些复杂的自动化场景,更建议使用 Selenium、Pyppeteer、Helium 等

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 自动化,Helium 凭什么取代 Selenium?

来自AirPython哥的分享。

1. Helium 是什么?

Helium 是一款 Web 端自动化开源框架,全称是:Selenium-Python-Helium,从名字上就可以看出,Helium 似乎和 Selenium 息息相关

确实,Helium 针对 Selenium 进行了封装,它屏蔽了 Selenium 很多实现细节,提供了更加简洁直观的 API,更方便我们进行 Web 端的自动化

官方表示,要实现同样的功能,Helium 相比 Selenium 要少 30% – 50% 的代码

目前,Helium 仅支持 Chrome 和 FireFox

2.优缺点

Helium 主要包含下面 6 个优点:

  • Helium 自带 WebDriver,不需要下载、配置浏览器驱动
  • 内嵌页面 iframe 页面元素直接操作,不需要使用 switch_to.frame() 切换 iframe
  • 窗体管理更方便,可以直接使用窗口标题或部分标题内容来切换窗体
  • 隐式等待,针对某个元素执行点击操作,Selenium 如果元素没有出现,脚本会执行失败;而 Helium 默认最多等待 10s,等待元素出现后立马执行点击操作
  • 显式等待,Helium 提供更加优雅的 API 来等待页面元素出现
  • API 更简洁直观,代码量少

Helium 主要缺点,体现在:

  • 由于封装,屏蔽了很多细节,所以它不合适二次开发
  • 目前仅支持 Chrome 和 FireFox 浏览器
  • 版本更新慢、遗留 Bug 及文档少

3.准备一下

切换到对应的虚拟环境下,通过 pip 命令安装依赖即可

# 安装依赖
pip3 install helium

接着,我们在 IDE 中,使用 helium.__all__ 打印出它包含的属性及方法

我们发现,Helium 包含的操作动作、控件对象、键盘操作关键字基本覆盖了大部分的自动化操作场景

4.Selenium VS Helium

是骡子是马,拉出来溜溜 ~

接下来,我们以登录 126 邮箱为例,来比较 Selenium 和 Helium

1、传统 Selenium 实现

首先,我们需要下载并配置 WebDriver,然后实例化 WebDriver 对象,打开邮箱登录的主页面

from selenium import webdriver

# 实例化Driver
driver = webdriver.Chrome()
# 隐式等待10s
driver.implicitly_wait(10)
# 打开主页面
driver.get(home_url)

通过观察网页元素,发现输入框区域被包裹在 iframe 内嵌页面中

所以,我们需要使用 switch_to.frame() 函数切换到对应的 iframe,才能操作 iframe 内部的元素

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

# 显示等待打开主页面
wait = WebDriverWait(driver, 10, 0.5)

# 切换到对应的iframe,否则无法操作内部元素
wait.until(
    EC.frame_to_be_available_and_switch_to_it(driver.find_element_by_xpath('//iframe[contains(@id,"x-URS-iframe")]')))

接着,使用 Selenium API( 这里以 Xpath 为例 )查找用户名和密码输入框、登录按钮;输入用户名和密码,模拟登录操作

# 用户名输入框
element_input = wait.until(EC.visibility_of(driver.find_element_by_xpath('//input[@name="email"]')))
element_input.clear()
element_input.send_keys(username)

# 密码输入框
element_password = wait.until(EC.visibility_of(driver.find_element_by_xpath('//input[@name="password"]')))
element_password.clear()
element_password.send_keys(password)

# 登录按钮
wait.until(EC.element_to_be_clickable((By.XPATH, '//a[@id="dologin"]'))).click()

最后,通过某个页面元素是否出现来判断是否登录成功

# 找一个登录成功的页面元素
# 通过元素属性+元素值来唯一定位元素
result = True
try:
    element_recy_email = wait.until(EC.element_to_be_clickable((By.XPATH, '//span[@class="oz0" and contains(text(),"收 信")]')))
    if element_recy_email:
        result = True
    else:
        result = False
except Exception as e:
    result = False

print("邮箱登陆成功" if result else "邮箱登录失败")

2、Helium 实现

接下来,我们通过 Helium 的方式来实现这一操作

首先,我们只需要 2 行代码即可以打开主页

from helium import *

# 打开主页
driver = start_chrome(home_url)

# 等待元素加载完成
wait_until(Text("你的专业电子邮局").exists)

然后,通过内置 TextField 控件对象及预设文本内容,使用 write 动作输入用户名和密码

# 不需要切换iframe,直接输入
write(username,TextField('邮箱帐号或手机号码'))
write(password,TextField('输入密码'))

值得一提的是,Helium 不需要切换 iframe,可以直接操作内嵌页面元素,简直不要太方便!

# 模拟点击Enter键登录
press(ENTER)

通过 Helium 内置的 wait_until 方法 + 控件对象,可以显式等待元素出现,默认最长时间为 10s比如,这里等待登录完成的主页面加载完成,收件箱可以点击,执行一次点击操作

wait_until(Text('收 信').exists)

# 点击收件箱
click(Text('收 信'))

最后,调用 kill_browser() 方法关闭浏览器,结束自动化操作

# 退出
sleep(10)

# 关闭浏览器
kill_browser()

需要指出的是,Helium 使用 start_chrome() 方法返回的对象实际上就是 WebDriver 对象,可以结合 Selenium API 一起使用

5.最后

通过上面的对比发现,Helium 相比 Selenium 使用似乎更方便,但是它不适用于一些复杂的页面

因此,在实际自动化项目中,建议搭配 Selenium 和 Helium 使用,简单的页面使用 Helium,复杂的页面切换到 Selenium

如果你觉得文章还不错,请大家 点赞、分享、留言下,因为这将是我持续输出更多优质文章的最强动力!

Python 计算 瑞幸和星巴克 谁的门店最多

如果不借助他人的数据,你能自己算出瑞幸咖啡和星巴克咖啡其各自的门店数量吗?

让你自己算出一个精确的值,你会使用什么方法进行计算一线城市门店数量?

难度高一点点,你怎么样才能知道二线城市的门店总数,甚至是全国的门店数量?

用我们今天的方法,你可以知道,瑞幸咖啡在一线城市的数量是:1634间,而星巴克则为:1587间

往下看答案之前,你可以想想有几种方法可以实现我们的目的。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),准备开始输入命令安装依赖。

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南

输入以下命令安装我们所需要的依赖模块:

pip install requests

看到 Successfully installed xxx 则说明安装成功。你可以在Python实用宝典公众号后台回复:咖啡门店数 获得本文完整数据和代码。

2.获取门店数

怎么样,文章开头提出的问题你想到答案了吗?

其实很简单,那就是调用地图的接口进行门店搜索。 通过这个方法,我们不仅可以算出门店的数量,还能得到每个门店的对应位置,并且可以用来做后续的数据分析:

所以现在问题就转化为找到有提供搜索接口的地图供应商,而且这个接口得是免费的,因此我找了腾讯地图的接口:

https://lbs.qq.com/

你只需要上去注册账号,申请Key即可调用相关的接口,申请完了记得开webserviceAPI,选择签名校验的形式调用接口:

2.1 初始化

为了使用API,我们得先初始化请求链接及其所需要的参数:

class LocationSearch(object):

    def __init__(self, keyword: str):
        self.keyword = keyword
        self.key = '你的Key'
        self.sk = '你的校验sk'
        self.url = (
            'https://apis.map.qq.com/ws/place/v1/search?'
            'boundary=region({},0)&key={}&keyword={}'
            '&page_index={}&page_size=20'
        )

Key是在你申请API权限的时候就会分配给你的,而sk是在你选择 签名校验 的形式调用接口时分配给你的。

那么我们如何用这两个数据请求接口呢?请看下面这个函数:

def request_data(self, location: str, page: int):
    """
    请求接口数据
    Arguments:
        location {str} -- 地点
        page {int} -- 第几页
    
    Returns:
        {list} -- 该页该地点的数据
        {int} -- 该地点结果总数
    """
    # 拼接链接
    url = self.url.format(location, self.key, self.keyword, page)
    # 获得数字签名,并将签名加到链接后面进行请求
    wait_sig = url.split('qq.com')[1] + str(self.sk)
    sig = hashlib.md5(wait_sig.encode('utf-8')).hexdigest()
    res = requests.get(url + '&sig=' + sig)
    # 获得数据返回
    pois = res.json()['data']
    # 避免请求上限
    time.sleep(0.2)
    return pois, res.json()['count'] 

首先是将初始化的请求链接拼接起来,然后由于需要签名校验,因此我们得如下进行操作:

GET请求分为:域名,请求路径和参数三个部分,用于签名计算的有:
请求路径: /ws/place/v1/search?
请求参数: boundary=region({},0)&key={}&keyword={} &page_index={}&page_size=20
注意{}是待填充的

1. 首先对参数进行排序:按参数名升序(本例结果为 boundary 在前,key在后,如果第一个字母相同,要依据第二个字母升序):
boundary=region({},0)&key={}(….后面略)

2. 签名计算(sig):
请求路径+”?”+请求参数+SK进行拼接,并计算拼接后字符串md5值,即为签名(sig):
要求:请求参数必须是未进行任何编码(如urlencode)的原始数据
md5(” /ws/place/v1/search?boundary=region({},0)&key={}&keyword={} &page_index={}&page_size=20你的SK“)

计算得到结果类似为:22dxxxxxxxxxxxxxx2b0bcc0e50

3. 生成最终请求:将计算得到的签名sig,放到请求中(参数名即为:sig):
https://apis.map.qq.com/ws/place/v1/search? boundary=region({},0)&key={}&keyword={} &page_index={}&page_size=20&sig= 22dxxxxxxxxxxxxxx2b0bcc0e50

注意:计算 sig 要使用原始参数值,不要进行任何编码,但最终发送时的参数,是需要时行url编码的

最后拿到返回的值,里面带有所有结果的地理位置及结果的数量。

2.2 按地点返回结果

这一部分其实很简单,就是调用2.1的函数,然后实现分页保存变量,最后输出门店数量,返回数据。

def get_single_location(self, location: str):
    """
    获得单个地点的数据
    
    Arguments:
        location {str} -- 地点
    
    Returns:
        {list} -- 该地点某关键词的所有数据
        {int} -- 该地点某关键词的所有数量
    """
    page = 1
    location_data = []
    pois, total = self.request_data(location, page)
    for poisition in pois:
        location_data.append(poisition)
    # 如果有多页
    while (total / 20) > page:
        pois, _ = self.request_data(location, page)
        for poisition in pois:
            location_data.append(poisition)
        page += 1
    print(f'{self.keyword} {location} 门店总数为:{total}')
    return location_data, total 

计算一线城市的结果如下:

F:\push\20200315>python scrapy.py
瑞幸咖啡 北京 门店总数为:492
瑞幸咖啡 上海 门店总数为:581
瑞幸咖啡 广州 门店总数为:301
瑞幸咖啡 深圳 门店总数为:260

2.3 汇总结果并保存

接下来我们需要汇总2.2计算到的每个城市的数据,保存到json文件,并计算总数。

def get_cities_data(self, cities: str):
    """
    获得所有城市某关键词的数据
    
    Arguments:
        cities {list} -- 城市列表
    """
    result = []
    keyword_count = 0
    for city in cities:
        # 获得该城市的所有门店和总数
        data, count = self.get_single_location(city)
        keyword_count += count
        result.extend(data)
    print(f'{self.keyword} 一线城市门店总数为:{keyword_count}')
    # 导出数据
    with open(f'{self.keyword}.json', 'w') as my_file:
        json.dump(result, my_file, ensure_ascii=False) 

最终可以获得一个 瑞幸咖啡.json 的文件,里面存有每个城市的咖啡店精确位置,并输出一个总数,这样调用即可:

if __name__ == '__main__':
    cities = ['北京', '上海', '广州', '深圳']

    loc = LocationSearch('瑞幸咖啡')
    loc.get_cities_data(cities)

    loc = LocationSearch('星巴克咖啡')
    loc.get_cities_data(cities)

F:\push\20200315>python scrapy.py
瑞幸咖啡 北京 门店总数为:492
瑞幸咖啡 上海 门店总数为:581
瑞幸咖啡 广州 门店总数为:301
瑞幸咖啡 深圳 门店总数为:260
瑞幸咖啡 一线城市门店总数为:1634

星巴克 北京 门店总数为:380
星巴克 上海 门店总数为:797
星巴克 广州 门店总数为:209
星巴克 深圳 门店总数为:201
星巴克 一线城市门店总数为:1587

看来瑞幸咖啡一线城市里的门店数量已经超过星巴克了,不愧是割资本主义国家韭菜,造福中国老百姓的企业啊!

3.扩展

就像文章开头所提到的,如果你需要算出每个城市的咖啡店数量其实也很简单,咱可以调用下面这个接口请求腾讯地图的所有行政区数据,获得所有城市的名称:

https://apis.map.qq.com/ws/district/v1/list

不过我已经dump了一个,大家在Python实用宝典公众号后台回复:咖啡门店数 即可获得。

使用这一个,你只需要读取该csv文件提取所有城市名,然后放入cities变量中进行计算,如下代码所示:

if __name__ == '__main__':
    with open('cities.csv', 'r', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        cities = [row[0] for row in reader]

    loc = LocationSearch('瑞幸咖啡')
    loc.get_cities_data(cities)

    loc = LocationSearch('星巴克咖啡')
    loc.get_cities_data(cities)

不过,请注意一些特殊情况,比如说那个城市没有数据的时候,接口可能不会返回date数据,这时候要用字典的get方法进行处理:

# pois = res.json()['data']
pois = res.json().get('data', []) 

不过如果你要计算全国的数据的话,这个方法并不可靠,因为无法避免山寨店的存在,山寨店一样也会被记入到腾讯地图中,而一线城市的监管严格,比较少出现山寨店的情况,因此可以用这个方法计算。

我们的文章到此就结束啦,如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 一个超快的公共情报搜集爬虫

Photon是一个由s0md3v开源的情报搜集爬虫,其主要功能有:

1.爬取链接(内链、外链)。
2.爬取带参数的链接,如(pythondict.com/test?id=2)。
3.文件(pdf, png, xml)。
4.密钥(在前端代码中不小心被释放出来的)。
5.js文件和Endpoint(spring中比较重要的监视器)
6.匹配自定义正则表达式的字符串。
7.子域名和DNS相关数据。

你可以用它来干很多事,比如爬图片、找漏洞、找子域名、爬数据等等。而且提取出来的数据格式非常整洁:

不仅如此,它甚至支持json格式 ,仅需要在输入命令的时候加上json参数:

python photon.py -u "http://example.com" --export=json

为什么能用来做情报搜集呢?耐心往后看哦。

1.下载安装

你可以上photon的github下载完整项目:
https://github.com/s0md3v/Photon

或者关注下方Python实用宝典公众号在后台回复photon获得国内网盘下载地址。下载后解压到你想要使用的地方。如果你还没有安装Python,建议阅读这篇文章:超详细Python安装指南,进行Python的安装。

安装完Python后,打开CMD(windows)/Terminal(macOS),下面简称这两种为终端,进入你刚解压的文件夹,然后输入以下命令安装Photon的依赖:

pip install -r requirements.txt

如图所示:

2.简单使用

注意,使用的时候要在Photon文件夹下。比如我们随便提取一个网站的URL试一下,在终端输入以下命令:

python photon.py -u https://bk.tencent.com/

结果如下:

它会在当前目录下产生一个你测试的域名的文件夹,比如在我这里是 bk.tencent.com:

嘻嘻,让我们看看里面有什么东西,有没有程序员留下的小彩蛋,打开external.txt,这是该网站的外链的存放位置。可以看到,这里不仅仅是只有网站页面,连CDN文件地址都会放在这里,所以external可能是个藏宝哦。

还能一下找出该网站上链接的全部开源项目:

3.扩展

这个项目的价值,不仅在于能够快速拉取你想要得到的数据,还在于能够构建一个牛逼轰轰的情报系统(如果你技术够强的话)。因为它是能不断延伸下去的,比如从外链出发,你能找到很多和这个网站相关的讯息:

相比于搜索引擎搜索的结果,实际上这些信息更符合情报要求。因为不是所有的信息都能在搜索引擎搜索得到,而通过这个Photon,你可以顺藤摸瓜找到那些隐藏在互联网世界的它们。试想一下,如果你搜集了很多这样的网站…然后用正则表达式搭建一个属于你自己的搜索引擎,这样的感觉是不是很棒?

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 你见过三行代码的爬虫吗

Python实用宝典每次讲爬虫的时候都会从“发送请求” 开始讲,讲到解析页面的时候可能大部分读者都会卡住,因为这部分确实需要一点XPATH或者CSS选择器的前置知识。那么有没有不需要这么复杂的操作就能把页面信息读取出来的方法呢?

答案是:有。

Lassie 是一个超简单的页面信息检索工具,它能够通过几行代码就获取到页面上的静态信息,比如:页面描述、视频链接、页面标题,页面关键词、图像链接等等。

为什么超简单?感受一下:

import lassie
data = lassie.fetch('https://www.zhihu.com')
print(data) 

你只要fetch一下页面,就能得到以下的运行结果(输出为字典):

(base) F:\push\20191112>python test.py
 {'images': [{'src': 'https://static.zhihu.com/static/favicon.ico', 'type': 'favicon'}], 'videos': [], 'description': '有问题,上知乎。知乎,可信赖的问答社区,以让每个人高效获得可信赖的解答为使命。知乎
 凭借认真、专业和友善的社区氛围,结构化、易获得的优质内容,基于问答的内容生产方式和独特的社区机制,吸
 引、聚集了各行各业中大量的亲历者、内行人、领域专家、领域爱好者,将高质量的内容透过人的节点来成规模地
 生产和分享。用户通过问答等交流方式建立信任和连接,打造和提升个人影响力,并发现、获得新机会。', 'locale': 'zh_CN', 'url': 'https://www.zhihu.com', 'title': '知乎 - 有问题,上知乎', 'status_code': 200} 

1.安装

如果你还没有安装Python,推荐阅读这篇文章:Python安装

安装完成后,请打开你的CMD/Terminal(终端)输入以下命令:

pip install lassie

即可成功安装lassie.

2.使用

现在,用这个工具爬取我们上篇文章的图片链接吧!

import lassie
data = lassie.fetch('https://pythondict.com/ai/python-suicide-detect-svm/')
print(data['images'])

结果:

[{'src': 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'secure_src': 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'type': 'og:image'}, {'src': 
 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'type': 'twitter:image'}, 
 {'src': 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/07/2019073115192114.jpg', 'type': 'favicon'}]

当然,我们还可以用列表解析式,把所有链接放到一个数组里:

print([i['src'] for i in data['images']])

结果:

['https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/07/2019073115192114.jpg']

怎么样,是不是这个工具拿来爬静态页面实在太方便了!唯一的缺点就是它无法爬取页面中详细的文本内容,仅仅只能用来提取图片、视频和页面相关的信息,如果你的爬虫是只需要爬取静态页面上的图片和视频,那这个简直是神器啊。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 爬取“微博树洞”详细教程

最近要做一个关于自动从微博等短文本数据中判断人是否有自杀倾向的项目,在这之前需要先收集许多具有自杀倾向的人发的微博或短文本数据作为训练集。

其实这样的数据是挺难找的,尤其是对于我这种需求量比较大的项目。不过好在最后发现了突破口:“微博树洞”。“微博树洞”是指宣告了自杀行为的过世的人的微博,其留言区成为成千上万的抑郁症或是绝望的人的归属,在其下方发布许多负能量甚至是寻死的宣言。

比如走饭的微博:

1.找到微博评论数据接口

微博评论的数据接口有两种,一种是手机版、一种是PC版。手机版能爬到的数据仅仅只有十五页,因此我们从PC版入手,先来看看PC版的接口怎么找,长啥样儿。

首先,在当前微博的页面右键—检查(F12)打开开发者工具,然后按照下图的步骤进行操作(选择NetWork—选择XHR—随便点击另一个评论页—查看右侧新增的请求):

然后我们看新增的请求,你会发现在Preview中能看到格式化后的数据,而且里面有个html,仔细观察这个html你会发现这个就是评论列表的数据。我们仅需要将这个html解析出来即可。

再看看get请求的URL:

https://weibo.com/aj/v6/comment/big?ajwvr=6&id=3424883176420210&page=2&__rnd=1573219876141

ajwvr是一个固定值为6、id是指想要爬取评论的微博id、page是指第几页评论、_rnd是请求时的毫秒级时间戳。

不过微博是要求登录才能看更多评论的,因此我们需要先访问微博,拿到cookie的值才能开始爬。

2.编写爬虫

关注文章最下方的Python实用宝典,回复微博评论爬虫即可获得本项目的完整源代码。

设定四个参数:

    params = {
        'ajwvr': 6,
        'id': '3424883176420210',
        'page': 1,
        '_rnd': int(round(time.time() * 1000))
    } 

设定cookie:

headers = { 
    'X-Requested-With': 'XMLHttpRequest', 
    'Cookie': '你的微博cookie',
} 

发送请求并解析数据

    URL = 'https://weibo.com/aj/v6/comment/big'

    for num in range(1,51,1):
        print(f'============== 正在爬取第 {num} 页 ====================')
        params['page'] = num
        params['_rnd'] = int(round(time.time() * 1000))
        resp = requests.get(URL, params=params, headers=headers)
        resp = json.loads(resp.text) 

解析这串HTML中我们所需要的数据,这里用到了XPATH,如果你还不了解XPATH,可以看这篇文章: 学爬虫利器XPath,看这一篇就够了

         if resp['code'] == '100000':
            html = resp['data']['html']
            html = etree.HTML(html)
            data = html.xpath('//div[@node-type="comment_list"]')
            for i in data:
                # 评论人昵称
                nick_name = i.xpath('.//div[@class="WB_text"]/a[1]/text()')
                # 评论内容
                text = i.xpath('.//div[@class="WB_text"]')
                text = [i.xpath('string(.)') for i in text]
                # 头像地址
                pic_url = i.xpath('.//div[@class="WB_face W_fl"]/a/img/@src')
                print(len(nick_name),len(text),len(pic_url))
                write_comment([i.strip() for i in text], pic_url, nick_name) 

其中写入文件的函数和下载图片的函数如下:

# 下载图片
def download_pic(url, nick_name):
    if not url:
        return
    if not os.path.exists(pic_file_path):
        os.mkdir(pic_file_path)
    resp = requests.get(url)
    if resp.status_code == 200:
        with open(pic_file_path + f'/{nick_name}.jpg', 'wb') as f:
            f.write(resp.content)

# 写入留言内容
def write_comment(comment, pic_url, nick_name):
    f = open('comment.txt', 'a', encoding='utf-8')
    for index, i in enumerate(comment):
        if ':' not in i and '回复' not in i and i != '':
            # 去除评论的评论
            w_comment = i.strip().replace(':', '').replace('\n', '')
            # 写入评论
            f.write(w_comment.replace('等人', '').replace('图片评论', '')+'\n')
            # 获得头像
            download_pic(pic_url[index], nick_name[index]) 

以上就是我们所用到的代码。在公众号后台回复 微博评论爬虫 即可下载完整源代码(附手机版爬虫)。

3.定时爬虫

尽管如此,我们得到的数据还是不够,PC版的微博评论页面也仅仅支持爬到第五十页,第五十一页后就拿不到数据了,如图:

不过,走饭这个微博真的很多人回复,一天的数据就差不多50页了,我们可以通过每天定时爬50页来获取数据。linux系统可以使用crontab定时脚本实现,windows系统可以通过计划任务实现,这里讲讲crontab实现方法。

假设你的Python存放在/usr/bin/且将脚本命名为weibo.py 存放在home中,在终端输入crontab -e后,在最后面增加上这一条语句即可:

0 0 * * * /usr/bin/python /home/weibo.py

在公众号后台回复 微博评论爬虫 即可下载本文完整源代码(附手机版爬虫) 。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 批量下载网易云音乐歌单

网易云音乐有非常优秀的分享氛围,有许多好听的歌单,不过有时候我们想要下载这些歌单到自己的MP4或可移动存储设备却非常麻烦:要么是有VIP但歌单歌曲太多、一个一个下载非常麻烦,要么是没VIP无法下载一些歌曲。今天给大家推荐一种基于Python的下载方法,可以批量免VIP下载歌单音乐

作者直接将其用 wxPython做成了一个exe程序,如果你想直接使用但是却上不了github的话,请扫描关注最下方Python实用宝典公众号二维码,回复 网易云音乐下载 获得程序和源代码。开源项目地址: 网易云音乐歌曲批量下载,免VIP【支持歌单,排名榜】

1.爬取原理

1.1 通过接口下载歌曲

我们知道,可在线播放的音乐大部分存在可以直接访问下载音乐的链接,这就是它的真实外链地址。而网易云音乐的真实外链地址是:

https://music.163.com/song/media/outer/url?id=%E6%AD%8C%E6%9B%B2id.mp3&_=1

只要通过获得歌单的所有歌曲ID,然后将其替换到这个真实外链地址中,我们就能够实现歌曲的批量下载。这份开源代码的作者没有使用异步的形式进行下载,如果你想要下载的歌单歌曲非常多的话,建议你将其改成异步的形式,具体的教程可见我们之前的文章:Python 异步批量下载

1.2 获得歌单所有的歌曲ID

可以随意打开一个歌单,比如网 易 10w 评 论 的 热 歌. 使用开发者工具,可以非常轻易地定位到歌单里的音乐的链接:

而这个链接的后面 id=xxxxxx 就是这首歌曲的id,我们仅需要定位到这些链接的css,使用beautifulsoup即可获得它们的id。看看作者是怎么写的:

2. 程序使用方法

将你想要下载的歌单地址放入这个exe程序即可:

手机版网易云音乐,仅需要进入歌单,然后点击分享按钮,就可复制链接获得歌单地址:

然后把这个地址放入程序中即可开始批量下载啦,怎么样,是不是非常方便的工具?感谢原作者的分享,给它点个star吧!

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

音乐相关教程:

Python 批量下载网易云音乐歌单

Python 制作音乐高潮副歌提取器

Python Django快速开发音乐高潮提取网(1)

Python Django快速开发音乐高潮提取网(2)

Python Django快速开发音乐高潮提取网(3)

Python 超方便超快速剪辑音乐

Python 提取音乐频谱并可视化

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 反编译调用有道翻译(附完整代码)

网易有道翻译是一款非常优秀的产品,他们的神经网络翻译真的挺无敌。无奈有道客户端实在是太难用了,而且在某些具体场景(比如对网站进行批量翻译)无法使用,而有道的云服务又特别的贵,一般人是无法支付得起的。

然而理论上而言,所有看得见的东西都是爬得到的,有道翻译接口也一样。为了祖国未来花朵(咸鱼) 的发展,今天就来给大家介绍一下如何用 Python超简单快速地调用有道翻译得到翻译结果 。此外,本教程仅供学习哦。

如果你懒得看教程,只想要拿到源代码,请关注Python实用宝典公众号并回复:“Python有道接口” 。

1.找到翻译相关接口

打开 fanyi.youdao.com 随便输入一个单词进行翻译,使用开发者工具(空白处右键检查或F12)查看请求数据。

可以看到,请求的接口是:
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule

开发者工具往下拉,查看Form Data得到请求的body是:

  1. i: 你好
  2. from: AUTO
  3. to: AUTO
  4. smartresult: dict
  5. client: fanyideskweb
  6. salt: 15707931034929
  7. sign: 99d0fc48506346afc40e36d5648cc320
  8. ts: 1570793103492
  9. bv: ca3dedaa9d15daa003dbdaaa991540d1
  10. doctype: json
  11. version: 2.1
  12. keyfrom: fanyi.web
  13. action: FY_BY_REALTlME

2.解析请求body内容

显然,以上body内容中,i 是需要翻译的文本,from是原文语言,to是翻译语言。我们其他的参数只需要设置为一致的即可。现在需要解决这几个参数:salt, sign, bv,ts.

ts从格式上看就知道是时间戳,而且ts和salt内容很接近,且只差了一位,可以合理猜测,salt就是ts+1位随机数。

接下来就差sign和bv,这两个值看起来非常像MD5,不过不确定是什么参数的MD5,因此需要阅读前端源代码。

在performance中录制,重新请求接口,找到翻译接口的前端代码(fanyi.min.js).然后搜索我们的关键词sign或者bv. 使用debug工具查看值的流动。

从这里我们可以知道,bv 即浏览器头部信息MD5的值,我的浏览器头部是这样的: “5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36”

实际上在请求接口的时候随便用什么头部都能过这个校验,只要符合标准就行。

最后一个未知参数是sign. 同样,我们打开debug模式,输入信息,就可以得到其值了。

很显然,sign由n.md5(“fanyideskweb” + e + i + “n%A-rKaT5fb[Gy?;N5@Tj”)组成,而e根据debug显示的结果,就是我们需要翻译的信息,而i就是salt. 因此4个参数我们全部成功反编译!

3. 用Python调用接口进行翻译

我们只需要伪造请求的body,向接口发送post请求即可得到翻译结果。比如,ts是13位时间戳,在Python中可以使用time.time()*1000获得:

ts = str(int(time.time()*1000))

salt是ts+一位随机数,太简单了:

salt = ts + str(random.randint(0, 9))

bv是浏览器User-Agent,需要进行MD5计算,我们新建一个MD5函数,将字符串传入函数获得MD5。

def get_md5(string):
    string = string.encode('utf-8')
    md5 = hashlib.md5(string).hexdigest()
    return md5
bv = get_md5("5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")

sign是四个字符串组成后进行MD5的结果:

sign = get_md5("fanyideskweb" + context + salt + "n%A-rKaT5fb[Gy?;N5@Tj") 

这样,我们获得了所有需要用到的参数,集合在一起后发送post请求。

试一下效果:

print(translation('你好')) 

成功得到接口返回的翻译结果:

(base) F:\push\20191011>python YouDaoSpider.py
hello 

关注下方的公众号,回复 “Python有道接口“即可获得全部源代码。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

爬虫工具篇 – 必会用的 6 款 Chrome 插件

在日常 PC 端的爬虫过程工作中,Chrome 浏览器是我们常用的一款工具

鉴于 Chrome 浏览器的强大,Chrome 网上应用商店很多强大的插件可以帮助我们快速高效地进行数据爬虫

今天推荐的 6 款 Chrome 插件,可以大大提升我们的爬虫效率。

EditThisCookie  

EditThisCookie 是一个 Cookie 管理器,可以很方便的添加,删除,编辑,搜索,锁定和屏蔽 Cookies。

可以将登录后的 Cookies 先保存到本地,借助 cookielib ,直接爬取登录后的数据。

避免了抓包和模拟登录,帮助我们快速地进行爬虫

Web Scraper

Web Scraper 是一款免费的、适用于任何人,包含没有任何编程基础的爬虫工具

操作简单,只需要鼠标点击和简单的配置,就能快速的爬取 Web 端的数据。

它支持复杂的网站结构,数据支持文本、连接、数据块、下拉加载数据块等各种数据类型。

此外,还能将爬取的数据导出到 CSV 文件中。

Xpath Helper

Xpath Helper 是一种结构化网页元素选择器,支持列表和单节点数据获取,

它可以快速地定位网页元素。

对比 Beautiful Soup,由于 Xpath 网页元素查找性能更有优势;Xpath 相比正则表达式编写起来更方便。

编写 Xpath 之后会实时显示匹配的数目和对应的位置,方便我们判断语句是否编写正确。

Toggle JavaScript

Toggle JavaScript 插件可以用来检测当前网页哪些元素是通过 AJAX 动态加载的。

使用它可以快速在容许加载 JS 、禁止加载 JS 两种模式中切换。

User-Agent Switcher for Chrome

User-Agent Switcher for Chrome 插件可以很方便的修改浏览器的 User-Agent。

可以模拟不同的浏览器、客户端,包含 Android、IOS 去模拟请求。

对于一些特殊网站,切换 User-Agent 可以更方便地进行数据爬取。

JSON-handle

JSON-handle 是一款功能强大的JSON数据解析Chrome插件。它以简单清晰的树形图样式展现 JSON 文档,并可实时编辑。针对数据量大的场景,可以做局部选取分析。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们。有任何问题请在下方留言,我们会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 超简单爬取新浪微博数据 (高级版)

新浪微博的数据可是非常有价值的,你可以拿来数据分析、拿来做网站、甚至是*****。不过很多人由于技术限制,想要使用的时候只能使用复制粘贴这样的笨方法。没关系,现在就教大家如何批量爬取微博的数据,大大加快数据迁移速度!

我们使用到的是第三方作者开发的爬虫weiboSpider(有工具当然要用工具啦)。这里默认大家已经装好了Python,如果没有的话可以看我们之前的文章:Python详细安装指南

1. 下载项目

进入下方的网址,点击Download ZIP下载项目文件

https://github.com/dataabc/weiboSpider

或者

你有git的话可以在cmd/terminal中输入以下命令安装​

git clone https://github.com/dataabc/weiboSpider.git 

​2.安装依赖

将该项目压缩包解压后,打开你的cmd/Termianl进入该项目目录,输入以下命令:

pip install -r requirements.txt

便会开始安装项目依赖,等待其安装完成即可。

3.设置cookie

打开weibospider文件夹下的weibospider.py文件,将”your cookie”替换成爬虫微博的cookie,具体替换位置大约在weibospider.py文件的22行左右。cookie获取方法:

3.1 登录微博

3.2 按F12键或者右键页面空白处—检查,打开开发者工具

3.3 选择network — 按F5刷新一下 — 选择第一个文件 — 在右边窗口找到cookie

然后替换大约在weibospider.py文件的22行左右的cookie,如图所示:

替换前:

替换后:

4.设置要爬的用户user_id

4.1 获取user_id

点开你希望爬取的用户主页,然后查看此时的url:

你会发现有一串数字在链接中,这个就是我们要用到的userID, 复制即可。

4.2 设置要爬取的user_id

打开config.json文件,你会看到如下内容:

{
    "user_id_list": ["1669879400"],
    "filter": 1,
    "since_date": "2018-01-01",
    "write_mode": ["csv", "txt"],
    "pic_download": 1,
    "video_download": 1,
    "cookie": "your cookie",
    "mysql_config": {
        "host": "localhost",
        "port": 3306,
        "user": "root",
        "password": "123456",
        "charset": "utf8mb4"
    }
}

下面讲解每个参数的含义与设置方法。

设置user_id_list
user_id_list是我们要爬取的微博的id,可以是一个,也可以是多个,例如:

"user_id_list": ["1223178222", "1669879400", "1729370543"],

上述代码代表我们要连续爬取user_id分别为“1223178222”、 “1669879400”、 “1729370543”的三个用户的微博。

user_id_list的值也可以是文件路径,我们可以把要爬的所有微博用户的user_id都写到txt文件里,然后把文件的位置路径赋值给user_id_list。

在txt文件中,每个user_id占一行,也可以在user_id后面加注释(可选),如用户昵称等信息,user_id和注释之间必需要有空格,文件名任意,类型为txt,位置位于本程序的同目录下,文件内容示例如下:

1223178222 胡歌
1669879400 迪丽热巴
1729370543 郭碧婷

假如文件叫user_id_list.txt,则user_id_list设置代码为:

"user_id_list": "user_id_list.txt",

如果有需要还可以设置Mysql数据和MongoDB数据写入,如果不设置的话就默认写入到txt和csv文件中。

5. 运行爬虫

打开cmd/terminal 进入该项目目录,输入:

python weibospider.py

即可开始爬取数据了,怎么样,是不是超级方便?而且你还可以自定义爬取的信息,比如微博的起始时间、是否写入数据,甚至能在它代码的基础上增加新的功能!(比如加个cookie池或者代理池之类的)

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典