抓取网页生成电子书(微信公众号【出书啦】效果纸质书效果代码思路获取)

优采云 发布时间: 2022-03-01 11:23

  抓取网页生成电子书(微信公众号【出书啦】效果纸质书效果代码思路获取)

  [目录]

  为您的个人微信朋友圈数据生成电子书!介绍

  朋友圈留着你的数据,留着美好的回忆,记录着我们的每一点成长。从某种意义上说,发朋友圈就是记录生活,感受生活,见证每个人每一步的成长。

  如此珍贵的记忆,何不保存呢?只需一杯咖啡时间,即可一键打印朋友圈。可以是纸质书也可以是电子书,可以长期保存,比拍照好,有时间足迹记忆。

  现在,您可以选择打印电子书或纸质书。如果印刷纸质书,可以找第三方机构购买;如果你打印一本电子书,我们可以自己生成,这样可以节省很多钱。

  部分截图

  在开始编写代码思路之前,我们先来看看最终生成的效果。

  电子书效果

  

  

  纸书效果

  

  获取微信书籍链接的代码思路

  看完效果图,开始进入代码编写部分。首先,由于朋友圈数据的隐私性较高,如果手动获取,需要使用root安卓手机解密或解密PC机备份的聊天记录数据库,很难大多数人。所以我们的想法是根据现有数据打印电子书。

  目前已经有第三方服务支持导出朋友圈数据,微信公众号【出版图书】提供了这样的服务。这种服务很有可能是基于安卓模拟器自动化的,我就不赘述了。

  先关注公众号,然后开始制作微信书籍。这个过程将你添加为编辑的朋友,然后你向他打开朋友圈。过一会采集,小编会给你发一个专属链接,这个链接里的内容就是你的Personal Moments。

  生成电子书

  有了这个链接,我们开始打印页面的内容。

  整个过程基于 selenium 自动化。如果你知道 selenium,那么这个过程其实很简单。

  首先,为了引导用户输入微信图书链接,我们采用在浏览器中弹出输入文本框的形式,让用户输入数据。

  首先在selenium中执行js代码,完成js代码中弹出输入文本框的功能。

  进入微信图书链接

  # 以网页输入文本框形式提示用户输入url地址

def input_url():

# js脚本

random_id = [str(random.randint(0, 9)) for i in range(0,10)]

random_id = "".join(random_id)

random_id = 'id_input_target_url_' + random_id

js = """

// 弹出文本输入框,输入微信书的完整链接地址

target_url = prompt("请输入微信书的完整链接地址","https://");

// 动态创建一个input元素

input_target_url = document.createElement("input");

// 为其设置id,以便在程序中能够获取到它的值

input_target_url.id = "id_input_target_url";

// 插入到当前网页中

document.getElementsByTagName("body")[0].appendChild(input_target_url);

// 设置不可见

document.getElementById("id_input_target_url").style.display = 'none';

// 设置value为target_url的值

document.getElementById("id_input_target_url").value = target_url

"""

js = js.replace('id_input_target_url', random_id)

# 执行以上js脚本

driver.execute_script(js)

  上述js代码的具体步骤为:弹出一个输入文本框,创建一个动态元素,随机命名元素的id,将动态元素插入到当前页面,这样就可以通过python 内容中的硒。

  接下来,检测弹框是否存在于 selenium 中。如果不存在,则获取弹框的内容并执行下一步。流程代码如下:

  # 执行以上js脚本

driver.execute_script(js)

# 判断弹出框是否存在

while(True):

try:

# 检测是否存在弹出框

alert = driver.switch_to.alert

time.sleep(0.5)

except:

# 如果抛异常,说明当前页面不存在弹出框,即用户点击了取消或者确定

break

# 获取用户输入的链接地址

target_url = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, random_id)))

value = target_url.get_attribute('value')

# 删除空格

value = value.strip()

  此时value的值就是弹出框返回的内容。(你可能会问,直接加value=微信书链接可以吗?其实>_header确实是可以的,通过selenium隐藏这个元素的代码如下:

  # 隐藏导航栏,防止影响截图效果

js = 'document.querySelector("body > header").style.display="none";'

driver.execute_script(js)

  我们也发现当前页面显示的数据只收录某月的朋友圈数据,而不是所有的朋友圈数据,那么如何显示所有的朋友圈数据呢?通过分析可以看出,当点击“下个月”按钮时,会显示一个新的元素,而原来的元素会被隐藏,隐藏的元素就是上个月的数据。所以我们只需要遍历到上个月,显示之前的所有元素,然后打印出来。那么,如何判断是上个月呢?我们也可以通过分析得知,当不是上个月时,“下个月”的类名是下个月,当是上个月时,“下个月”的类名是下个月禁用,所以我们可以检测它的类名,就知道是不是在上个月了。

  # 判断当下一月控件的class name 是否为next-month disable,如果是,则说明翻到最后一月了

page_source = driver.page_source

# 每一个element代表每一页,将每一页中style的display属性改成block,即可见状态

for index, element in enumerate(element_left_list):

# ..在xpath中表示上一级的元素,也就是父元素

parent_element = element.find_element_by_xpath('..')

# 获取这个父元素的完整id

parent_element_id = parent_element.get_attribute('id')

# 将该父元素更改为可见状态

js = 'document.getElementById("{}").style.display="block";'.format(parent_element_id)

driver.execute_script(js)

  但是,这种方式会出现问题。即使我们打印成功,我们也不难保证页面上的所有元素都加载完毕,所以有些元素打印后可能无法显示,导致不太好看。因此,需要判断加载何时结束。

  

  通过分析我们知道,网页元素未加载时,会出现“加载中”的提示,而网页元素加载时,该元素是隐藏的。因此,我们可以通过判断元素是否隐藏来知道当前页面元素是否被加载。这部分代码如下:

  # 等待当前页面所有数据加载完毕,正常情况下数据加载完毕后,这个‘加载中’元素会隐藏起来

while (True):

loading_status = WebDriverWait(driver, 20).until(

EC.presence_of_element_located((By.CSS_SELECTOR, 'div.j-save-popup.save-popup')))

if (loading_status.is_displayed() == False):

break

  但是我们也发现,在等待页面元素及时加载后,还是有一些图片没有显示出来。

  

  这很令人困惑,为什么?通过分析我们还了解到,当这些图片处于加载状态时,类名是lazy-img。从字面意思上,我们大概可以猜到它的意思是延迟加载,也就是用户在那里滑动页面,直到加载完毕。,以节省服务器压力。

  所以我们可以通过一个名为lazy-img的类滑动到每个元素来加载它。所以?一个合适的方法是通过js定位元素,直到所有类名为lazy-img的元素都不存在。

  while(True):

try:

lazy_img = driver.find_elements_by_css_selector('img.lazy-img')

js = 'document.getElementsByClassName("lazy-img")[0].scrollIntoView();'

driver.execute_script(js)

time.sleep(3)

except:

# 找不到控件img.lazy-img,所以退出循环

break

  其中document.getElementsByClassName("lazy-img")[0]是指document.getElementsByClassName("lazy-img")的第一个元素,scrollIntoView()是指滚动到该元素的位置

  打印电子书

  通过以上步骤,我们成功隐藏了一些可能影响外观的元素,同时也显示了所有需要的元素。接下来,是时候打印零件了。浏览器打印功能可以直接通过js代码调用,而且我们之前已经设置为自动打印pdf格式,所以会自动打印为pdf。但它打印到哪里?这里需要设置浏览器的默认存储位置,保存位置为当前目录。此步骤的代码如下:

  # 默认下载、打印保存路径

'savefile.default_directory': os.getcwd()

# 调用chrome打印功能

driver.execute_script('window.print();')

  打印后设置退出浏览器 driver.quit()

  经测试,电子书为超清版,大小约为16MB,质量还不错。

  如何运行

  # 跳转到当前目录

cd 目录名

# 先卸载依赖库

pip uninstall -y -r requirement.txt

# 再重新安装依赖库

pip install -r requirement.txt

# 开始运行

python main.py

  补充

  完整版源码存放在github上,需要的可以下载

  项目持续更新中,欢迎您star此项目

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线