جلب محتوى الموقع
هناك بالفعل العديد من الأدوات الجاهزة التي يمكنها استخراج محتوى المواقع الإلكترونية. ومع ذلك، إذا استخدمناها، لن نتمكن من فهم العملية الكامنة بشكل أفضل. إذا واجهنا في العمل مواقع معقدة أو خاصة، قد لا نحصل على النتائج المرجوة باستخدام هذه الأدوات. نحتاج إلى بناء الأدوات بأنفسنا، لفهمها بشكل أفضل واستخدامها بشكل أكثر فعالية.
دعونا نلقي نظرة أيضًا على بعض الأدوات الجاهزة المتاحة.
مُنقِّب البيانات
Data Miner
هو إضافة ملائمة جدًا على متصفح Chrome. يمكن استخدامه لاستخراج الروابط والمحتوى بسهولة.
getbook
getbook
هو أداة مفيدة جدًا لإنشاء الكتب الإلكترونية.
pip install getbook
{
"title": "كتابي",
"author": "اسم المؤلف",
"description": "وصف الكتاب",
"language": "ar",
"plugins": [
"highlight",
"search",
"lunr"
]
}
{
"uid": "book",
"title": "مرحبًا بالعالم",
"author": "Armin",
"chapters": [
"http://lucumr.pocoo.org/2018/7/13/python/",
"http://lucumr.pocoo.org/2017/6/5/diversity-in-technology",
]
}
getbook -f ./book.json --mobi
بهذه الطريقة، تم تحويل بعض الروابط بسهولة إلى كتاب إلكتروني. باستخدام Data Miner
و getbook
، حيث يقوم الأول بجمع الروابط والثاني بتحويلها إلى كتاب إلكتروني، يمكن إنشاء كتب إلكترونية بسهولة.
محاضرات فيزياء فاينمان
في فصل “مشروع عملي: تحويل محاضرات فيزياء فاينمان إلى كتاب إلكتروني”، تعلمنا كيفية تحويل صفحة ويب html
يتم عرضها باستخدام mathjax
إلى كتاب إلكتروني. هنا نستمر في هذا المشروع لنرى كيفية الحصول على جميع صفحات الويب. محاضرات فيزياء فاينمان تتكون من ثلاثة مجلدات. الصورة أعلاه توضح الفهرس للمجلد الأول.
http.client — عميل بروتوكول HTTP
الكود المصدري: Lib/http/client.py
يُعرّف هذا الوحدة فئات تُنفذ جانب العميل من بروتوكولي HTTP وHTTPS. عادةً لا يتم استخدامه مباشرةً — حيث يستخدمه الوحدة urllib.request للتعامل مع الروابط التي تستخدم HTTP وHTTPS.
انظر أيضًا: يُوصى باستخدام حزمة Requests لواجهة عميل HTTP ذات المستوى الأعلى.
من الواضح أن requests
هي واجهة برمجية ذات مستوى أعلى.
import requests
def main():
r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
print(r.status_code)
401
import requests
def main():
r = requests.get('https://github.com')
print(r.status_code)
print(r.text)
الوظيفة الرئيسية main()
```html
200
<html>
...
</html>
جربت، وتبين أن واجهة requests
تعمل بشكل صحيح.
<div class="toc-chapter" id="C03">
<span class="triangle">
â¶
</span>
<a class="chapterlink" href="javascript:Goto(1,3)">
<span class="tag">
الفصل 3.
</span>
علاقة الفيزياء بالعلوم الأخرى
</a>
<div class="sections">
<a href="javascript:Goto(1,3,1)">
<span class="tag">
3-1
</span>
مقدمة
</a>
<a href="javascript:Goto(1,3,2)">
<span class="tag">
3-2
</span>
الكيمياء
</a>
<a href="javascript:Goto(1,3,3)">
<span class="tag">
3-3
</span>
علم الأحياء
</a>
<a href="javascript:Goto(1,3,4)">
<span class="tag">
3-4
</span>
علم الفلك
</a>
<a href="javascript:Goto(1,3,5)">
<span class="tag">
3-5
</span>
الجيولوجيا
</a>
<a href="javascript:Goto(1,3,6)">
<span class="tag">
3-6
</span>
علم النفس
</a>
<a href="javascript:Goto(1,3,7)">
<span class="tag">
3-7
</span>
كيف حدث ذلك؟
</a>
</div>
</div>
هذا هو كود html
للفصل الثالث في صفحة الفهرس. أريد استخراج روابط كل فصل من هنا. <a href="javascript:Goto(1,3,7)">
، يمكن ملاحظة أنه رابط javascript
.
https://www.feynmanlectures.caltech.edu/I_03.html
ثم لاحظت أن مسارات كل فصل كانت منتظمة للغاية. على سبيل المثال، I_03.html
يشير إلى الفصل الثالث من المجلد الأول.
import requests
from bs4 import BeautifulSoup
from multiprocessing import Process
def scrape(chapter):
if chapter < 1 or chapter > 52:
raise Exception(f'chapter {chapter}')
chapter_str = '{:02d}'.format(chapter)
url = f'https://www.feynmanlectures.caltech.edu/I_{chapter_str}.html'
print(f'جارٍ استخراج {url}')
r = requests.get(url)
if r.status_code != 200:
raise Exception(r.status_code)
soup = BeautifulSoup(r.text, features='lxml')
f = open(f'./chapters/I_{chapter_str}.html', 'w')
f.write(soup.prettify())
f.close()
ملاحظة: تمت ترجمة النص الإنجليزي إلى العربية مع الحفاظ على أسماء الدوال والمتغيرات كما هي.
def main():
for i in range(52):
p = Process(target=scrape, args=(i+1))
p.start()
p.join()
main()
لنستمر في كتابة كود الزحف. هنا نستخدم Process
.
raise RuntimeError('''
RuntimeError:
تمت محاولة بدء عملية جديدة قبل أن تنتهي العملية الحالية
من مرحلة التمهيد الخاصة بها.
هذا يعني على الأرجح أنك لا تستخدم `fork` لبدء عملياتك الفرعية
وقد نسيت استخدام الأسلوب الصحيح في الوحدة الرئيسية:
if __name__ == '__main__':
freeze_support()
...
يمكن حذف سطر "freeze_support()" إذا لم يكن البرنامج
سيتم تجميده لإنتاج ملف قابل للتنفيذ. ```
def main():
for i in range(52):
p = Process(target=scrape, args=(i+1,))
p.start()
p.join()
ترجمة الكود إلى العربية:
def main():
for i in range(52):
p = Process(target=scrape, args=(i+1,))
p.start()
p.join()
ملاحظة: الكود يبقى كما هو لأنه مكتوب بلغة Python، ولا يتم ترجمة أسماء الدوال أو المتغيرات أو الأكواد البرمجية.
if __name__ == "__main__":
main()
def main():
start = timeit.default_timer()
ps = [Process(target=scrape, args=(i+1,)) for i in range(52)]
for p in ps:
p.start()
for p in ps:
p.join()
stop = timeit.default_timer()
print('الوقت: ', stop - start)
if __name__ == "__main__":
main()
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_01.html
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_04.html
...
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_51.html
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_52.html
الوقت: 9.144841699
<div class="figure" id="Ch1-F1">
<img src="img/FLP_I/f01-01/f01-01_tc_big.svgz">
<div class="caption empty">
<span class="tag">
الشكل 1â1
</span>
</div>
</div>
import requests
from bs4 import BeautifulSoup
from multiprocessing import Process
import timeit
def scrape(chapter):
if chapter < 1 or chapter > 52:
raise Exception(f'chapter {chapter}')
chapter_str = '{:02d}'.format(chapter)
url = f'https://www.feynmanlectures.caltech.edu/I_{chapter_str}.html'
print(f'جارٍ استخراج البيانات من {url}')
r = requests.get(url)
if r.status_code != 200:
raise Exception(r.status_code)
soup = BeautifulSoup(r.text, features='lxml')
f = open(f'./chapters/I_{chapter_str}.html', 'w')
f.write(soup.prettify())
f.close()
ملاحظة: تمت ترجمة النص الإنجليزي إلى العربية مع الحفاظ على أسماء الدوال والمتغيرات كما هي.
def main():
start = timeit.default_timer()
ps = [Process(target=scrape, args=(i+1,)) for i in range(52)]
for p in ps:
p.start()
for p in ps:
p.join()
stop = timeit.default_timer()
print('الوقت: ', stop - start)
if __name__ == "__main__":
main()
انظر إلى الرابط.
imgs = soup.find_all('img')
for img in imgs:
print(img)
ملاحظة: الكود أعلاه مكتوب بلغة Python ويستخدم مكتبة BeautifulSoup لاستخراج جميع عناصر <img>
من صفحة ويب. لا يحتاج الكود إلى ترجمة حيث أن الأوامر والمتغيرات مكتوبة بالإنجليزية وهي جزء من لغة البرمجة.
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_01.html
<img id="TwitLink" src=""/>
<img id="FBLink" src=""/>
<img id="MailLink" src=""/>
<img id="MobileLink" src=""/>
<img id="DarkModeLink" src=""/>
<img id="DesktopLink" src=""/>
<img src="img/camera.svg"/>
<img src="img/FLP_I/f01-00/f01-00.jpg"/>
<img data-src="img/FLP_I/f01-01/f01-01_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-02/f01-02_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-03/f01-03_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-04/f01-04_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-05/f01-05_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-06/f01-06_tc_big.svgz"/>
<img class="first" data-src="img/FLP_I/f01-07/f01-07_tc_iPad_big_a.svgz"/>
<img class="last" data-src="img/FLP_I/f01-07/f01-07_tc_iPad_big_b.svgz"/>
<img data-src="img/FLP_I/f01-08/f01-08_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-09/f01-09_tc_big.svgz"/>
<img data-src="img/FLP_I/f01-10/f01-10_tc_big.svgz"/>
https://www.feynmanlectures.caltech.edu/img/FLP_I/f01-01/f01-01_tc_big.svgz
ممنوع
ليس لديك إذن للوصول إلى هذا المورد.
Apache/2.4.38 (Debian) الخادم على www.feynmanlectures.caltech.edu المنفذ 443
```shell
% pip install selenium
جمع حزمة selenium
استخدام ملف selenium-3.141.0-py2.py3-none-any.whl المخزن مؤقتًا (904 كيلوبايت)
تم تلبية المتطلب urllib3 مسبقًا في /usr/local/lib/python3.9/site-packages (من selenium) (1.24.2)
تثبيت الحزم المجمعة: selenium
تم تثبيت selenium-3.141.0 بنجاح
export CHROME_DRIVER_HOME=$HOME/dev-env/chromedriver
export PATH="${PATH}:${CHROME_DRIVER_HOME}"
ترجمة:
export CHROME_DRIVER_HOME=$HOME/dev-env/chromedriver
export PATH="${PATH}:${CHROME_DRIVER_HOME}"
ملاحظة: النص أعلاه هو نص برمجي (shell script) ولا يتم ترجمته عادةً، حيث أن الأوامر والمتغيرات يجب أن تبقى كما هي لتعمل بشكل صحيح.
% chromedriver -h
الاستخدام: chromedriver [خيارات]
الخيارات
--port=PORT المنفذ الذي سيتم الاستماع عليه
--adb-port=PORT منفذ خادم adb
--log-path=FILE كتابة سجل الخادم إلى ملف بدلاً من stderr، يزيد مستوى السجل إلى INFO
--log-level=LEVEL تعيين مستوى السجل: ALL, DEBUG, INFO, WARNING, SEVERE, OFF
--verbose تسجيل بشكل مفصل (مكافئ لـ --log-level=ALL)
--silent عدم تسجيل أي شيء (مكافئ لـ --log-level=OFF)
--append-log إضافة إلى ملف السجل بدلاً من إعادة الكتابة
--replayable (تجريبي) تسجيل بشكل مفصل وعدم تقصير السلاسل الطويلة بحيث يمكن إعادة تشغيل السجل.
--version طباعة رقم الإصدار والخروج
--url-base بادئة مسار URL الأساسي للأوامر، على سبيل المثال wd/url
--readable-timestamp إضافة طابع زمني قابل للقراءة إلى السجل
--enable-chrome-logs عرض السجلات من المتصفح (يتجاوز خيارات التسجيل الأخرى)
--allowed-ips قائمة عناوين IP البعيدة المسموح لها بالاتصال بـ ChromeDriver، مفصولة بفواصل
# لا تقم بترجمة الكود البرمجي
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
تم استيراد المكتبات اللازمة من selenium
للتعامل مع متصفح الويب. هذه المكتبات تشمل:
webdriver
: للتحكم في المتصفح.By
: لتحديد العناصر في الصفحة باستخدام طرق مختلفة مثل الـ ID أو الاسم أو الـ CSS selector.Keys
: لإرسال ضغطات على لوحة المفاتيح مثل Enter أو Tab.WebDriverWait
: للانتظار حتى يتم تحميل عنصر معين في الصفحة.presence_of_element_located
: للتأكد من وجود عنصر معين في الصفحة قبل المتابعة.
with webdriver.Chrome() as driver:
wait = WebDriverWait(driver, 10)
driver.get("https://google.com/ncr")
driver.find_element(By.NAME, "q").send_keys("cheese" + Keys.RETURN)
first_result = wait.until(presence_of_element_located((By.CSS_SELECTOR, "h3>div")))
print(first_result.get_attribute("textContent"))
(تم الاحتفاظ بنص الكود كما هو لأنه لا يحتاج إلى ترجمة)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
import urllib
def main():
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get("https://www.feynmanlectures.caltech.edu/I_01.html")
elements = driver.find_elements(By.TAG_NAME, "img")
# print(dir(elements[0]))
print(driver.page_source)
i = 0
for element in elements:
# src = element.get_attribute('src')
element.screenshot(f'images/{i}.png')
i +=1
driver.close()
main()
from bs4 import BeautifulSoup
from multiprocessing import Process
import timeit
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
def img_path(chapter):
return f'./chapters/{chapter}/img'
def img_name(url):
splits = url.split('/')
last = splits[len(splits) - 1]
parts = last.split('.')
name = parts[0]
return name
ترجمة الكود إلى العربية:
def img_name(url):
# تقسيم الرابط إلى أجزاء بناءً على الشرطة المائلة '/'
splits = url.split('/')
# أخذ الجزء الأخير من القائمة الناتجة
last = splits[len(splits) - 1]
# تقسيم الجزء الأخير بناءً على النقطة '.'
parts = last.split('.')
# أخذ الجزء الأول من القائمة الناتجة (اسم الملف بدون الامتداد)
name = parts[0]
# إرجاع اسم الملف
return name
هذا الكود يستخرج اسم الملف من رابط URL دون الامتداد. على سبيل المثال، إذا كان الرابط هو https://example.com/images/photo.jpg
، فإن الدالة سترجع photo
.
def download_images(driver: webdriver.Chrome, chapter):
path = img_path(chapter)
Path(path).mkdir(parents=True, exist_ok=True)
elements = driver.find_elements(By.TAG_NAME, "img")
for element in elements:
src = element.get_attribute('src')
name = img_name(src)
element.screenshot(f'{path}/{name}.png')
تمت ترجمة الكود أعلاه إلى:
def download_images(driver: webdriver.Chrome, chapter):
path = img_path(chapter)
Path(path).mkdir(parents=True, exist_ok=True)
elements = driver.find_elements(By.TAG_NAME, "img")
for element in elements:
src = element.get_attribute('src')
name = img_name(src)
element.screenshot(f'{path}/{name}.png')
ملاحظة: تم الحفاظ على أسماء الدوال والمتغيرات كما هي لأنها أسماء برمجية ولا يتم ترجمتها.
USER_AGENT = ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15’
def scrape(chapter):
if chapter < 1 or chapter > 52:
raise Exception(f'chapter {chapter}')
chapter_str = '{:02d}'.format(chapter)
url = f'https://www.feynmanlectures.caltech.edu/I_{chapter_str}.html'
driver = webdriver.Chrome()
driver.get(url)
page_source = driver.page_source
Path(f'./chapters/{chapter_str}').mkdir(parents=True, exist_ok=True)
print(f'scraping {url}')
download_images(driver, chapter_str)
soup = BeautifulSoup(page_source, features='lxml')
imgs = soup.find_all('img')
for img in imgs:
if 'src' in img.attrs or 'data-src' in img.attrs:
src = ''
if 'src' in img.attrs:
src = img.attrs['src']
elif 'data-src' in img.attrs:
src = img.attrs['data-src']
del img.attrs['data-src']
name = img_name(src)
img.attrs['src'] = f'img/{name}.png'
f = open(f'./chapters/{chapter_str}/I_{chapter_str}.html', 'w')
f.write(soup.prettify())
f.close()
driver.close()
ترجمة الكود إلى العربية:
def scrape(chapter):
if chapter < 1 or chapter > 52:
raise Exception(f'chapter {chapter}')
chapter_str = '{:02d}'.format(chapter)
url = f'https://www.feynmanlectures.caltech.edu/I_{chapter_str}.html'
driver = webdriver.Chrome()
driver.get(url)
page_source = driver.page_source
Path(f'./chapters/{chapter_str}').mkdir(parents=True, exist_ok=True)
print(f'scraping {url}')
download_images(driver, chapter_str)
soup = BeautifulSoup(page_source, features='lxml')
imgs = soup.find_all('img')
for img in imgs:
if 'src' in img.attrs or 'data-src' in img.attrs:
src = ''
if 'src' in img.attrs:
src = img.attrs['src']
elif 'data-src' in img.attrs:
src = img.attrs['data-src']
del img.attrs['data-src']
name = img_name(src)
img.attrs['src'] = f'img/{name}.png'
f = open(f'./chapters/{chapter_str}/I_{chapter_str}.html', 'w')
f.write(soup.prettify())
f.close()
driver.close()
شرح الكود:
- يتم تعريف دالة
scrape
التي تأخذ رقم الفصل كمعامل. - يتم التحقق مما إذا كان رقم الفصل بين 1 و52، وإذا لم يكن كذلك، يتم إرجاع خطأ.
- يتم تحويل رقم الفصل إلى سلسلة نصية مكونة من رقمين (مثل “01” للفصل الأول).
- يتم إنشاء رابط URL بناءً على رقم الفصل.
- يتم فتح متصفح Chrome باستخدام
webdriver.Chrome()
. - يتم الانتقال إلى الرابط المحدد باستخدام
driver.get(url)
. - يتم حفظ مصدر الصفحة في المتغير
page_source
. - يتم إنشاء مجلد لحفظ الفصل إذا لم يكن موجودًا بالفعل.
- يتم طباعة رسالة تفيد بأنه يتم جلب البيانات من الرابط.
- يتم استدعاء دالة
download_images
لتنزيل الصور. - يتم تحليل مصدر الصفحة باستخدام
BeautifulSoup
. - يتم البحث عن جميع الوسوم
<img>
في الصفحة. - يتم تعديل مسار الصور بحيث تشير إلى الصور المحفوظة محليًا.
- يتم حفظ الصفحة المعدلة في ملف HTML.
- يتم إغلاق المتصفح.
def main():
start = timeit.default_timer()
ps = [Process(target=scrape, args=(i+1,)) for i in range(2)]
for p in ps:
p.start()
for p in ps:
p.join()
stop = timeit.default_timer()
print('الوقت: ', stop - start)
if __name__ == "__main__":
main()
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_01.html
جاري استخراج البيانات من https://www.feynmanlectures.caltech.edu/I_02.html
الوقت: 21.478510914999998
errpipe_read, errpipe_write = os.pipe()
OSError: [Errno 24] عدد كبير جدًا من الملفات المفتوحة
% ulimit a
ulimit: رقم غير صالح: a
lzw@lzwjava feynman-lectures-mobi % ulimit -a
-t: وقت المعالج (بالثواني) غير محدود
-f: حجم الملف (بالكتل) غير محدود
-d: حجم قطعة البيانات (بالكيلوبايت) غير محدود
-s: حجم المكدس (بالكيلوبايت) 8192
-c: حجم ملف الـ core (بالكتل) 0
-v: مساحة العنوان (بالكيلوبايت) غير محدود
-l: حجم الذاكرة المقفلة (بالكيلوبايت) غير محدود
-u: العمليات 2784
-n: واصفات الملفات 256
12
تنزيل_الصور
12
mathjax2svg
latexs 128
إنشاء_svg 0
إدراج_svg 0
إنشاء_svg 1
إدراج_svg 1
إنشاء_svg 2
إدراج_svg 2
إنشاء_svg 3
إدراج_svg 3
تحويل
12
تنزيل_الصور
12
mathjax2svg
latexs 0
latexs 0
تحويل
الوقت: 11.369145162
% grep --include=\*.html -r '\$' *
43/I_43.html:فترة زمنية طويلة $T$، يكون هناك عدد معين، $N$، من التصادمات. إذا كان
43/I_43.html:عدد التصادمات يتناسب مع الوقت $T$. نود أن
43/I_43.html:لقد كتبنا ثابت التناسب كـ $1/\tau$، حيث
43/I_43.html:$\tau$ سيكون له أبعاد الزمن. الثابت $\tau$ هو
43/I_43.html:هناك $60$ تصادمًا؛ إذن $\tau$ هو دقيقة واحدة. سنقول
43/I_43.html:أن $\tau$ (دقيقة واحدة) هو
خطأ E21018: فشل إنشاء نطاق Mobi محسن أثناء تحليل المحتوى في الملف. المحتوى: <In earlier chapters> الملف: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/069e0b8a-f12e-4102-aed3-977c0c3c1178/cTemp/mTemp/mobi-GxL1ye/OEBPS/c-49.xhtml السطر: 969
تحذير W28001: قارئ Kindle لا يدعم نمط CSS المحدد في المحتوى. يتم حذف خاصية CSS: 'max-width' الملف: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/069e0b8a-f12e-4102-aed3-977c0c3c1178/cTemp/mTemp/mobi-GxL1ye/OEBPS/stylesheet.css
تحذير W29004: تم إغلاق العلامة المفتوحة بشكل قسري: <span amzn-src-id="985"> الملف: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/069e0b8a-f12e-4102-aed3-977c0c3c1178/cTemp/mTemp/mobi-GxL1ye/OEBPS/c-4.xhtml السطر: 0000102
تحذير W29004: تم إغلاق العلامة المفتوحة بشكل قسري: <p amzn-src-id="975"> الملف: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/069e0b8a-f12e-4102-aed3-977c0c3c1178/cTemp/mTemp/mobi-GxL1ye/OEBPS/c-4.xhtml السطر: 0000102
تنبيه W14001: مشكلة في الارتباط التشعبي، لم يتم حلها بعد: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/97c9cb4d-35f7-4920-81eb-4705325c482f/cTemp/mTemp/mobi-pvawPN/OEBPS/c-1.xhtml#Ch1-F1
تنبيه W14001: مشكلة في الارتباط التشعبي، لم يتم حلها بعد: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/97c9cb4d-35f7-4920-81eb-4705325c482f/cTemp/mTemp/mobi-pvawPN/OEBPS/c-1.xhtml#Ch1-F2
تنبيه W14001: مشكلة في الارتباط التشعبي، لم يتم حلها بعد: /private/var/folders/_3/n3b7dq8x6652drmx6_d3t3bh0000gr/T/97c9cb4d-35f7-4920-81eb-4705325c482f/cTemp/mTemp/mobi-pvawPN/OEBPS/c-1.xhtml#Ch1-F3
<span class="disabled" href="#Ch1-F1">
1–1
</span>
تحويل 'OEBPS/84b8b4179175f097be1180a10089107be75d7d85.svg' إلى صورة نقطية بحجم 1264x1011
تحويل 'OEBPS/23a4df37f269c8ed43f54753eb838b29cff538a1.svg' إلى صورة نقطية بحجم 1264x259
Traceback (most recent call last):
File "runpy.py", line 194, in _run_module_as_main
File "runpy.py", line 87, in _run_code
File "site.py", line 39, in <module>
File "site.py", line 35, in main
File "calibre/utils/ipc/worker.py", line 216, in main
File "calibre/gui2/convert/gui_conversion.py", line 41, in gui_convert_override
File "calibre/gui2/convert/gui_conversion.py", line 28, in gui_convert
File "calibre/ebooks/conversion/plumber.py", line 1274, in run
File "calibre/ebooks/conversion/plugins/mobi_output.py", line 214, in convert
File "calibre/ebooks/conversion/plugins/mobi_output.py", line 237, in write_mobi
File "calibre/ebooks/oeb/transforms/rasterize.py", line 55, in __call__
File "calibre/ebooks/oeb/transforms/rasterize.py", line 142, in rasterize_spine
File "calibre/ebooks/oeb/transforms/rasterize.py", line 152, in rasterize_item
File "calibre/ebooks/oeb/transforms/rasterize.py", line 185, in rasterize_external
File "calibre/ebooks/oeb/base.py", line 1092, in bytes_representation
File "calibre/ebooks/oeb/base.py", line 432, in serialize
TypeError: لا يمكن تحويل كائن من نوع 'NoneType' إلى بايت
% kindlepreviewer feynman-lectures-on-physics-volumn-1.epub -convert
جارٍ التحقق من الوسائط المحددة.
جارٍ المعالجة المسبقة.
جارٍ معالجة 1/1 كتاب(كتب).
تم تحويل الكتاب مع وجود تحذيرات! : /Users/lzw/projects/feynman-lectures-mobi/feynman-lectures-on-physics-volumn-1.epub
جارٍ المعالجة اللاحقة.
جارٍ كتابة ملفات الإخراج/السجل إلى /Users/lzw/projects/feynman-lectures-mobi/output
تنظيف الملفات الظاهرية...
تقليم الملفات غير المستخدمة من الملفات الظاهرية...
إنشاء إخراج AZW3...
تسلسل الموارد...
تقسيم الترميز على فواصل الصفحات وحدود التدفق، إن وجدت...
إنشاء إخراج KF8
إنشاء ترميز KF8...
جدول العلامات لا يحتوي على aid وحجم القطعة كبير جدًا. يتم إضافته على أي حال.
جدول العلامات لا يحتوي على aid وحجم القطعة كبير جدًا. يتم إضافته على أي حال.
جدول العلامات لا يحتوي على aid وحجم القطعة كبير جدًا. يتم إضافته على أي حال.
ضغط الترميز...
إنشاء الفهارس...