I created python script to scrape facebook help page. I wanted to scrape cms_object_id
, cmsID
, name
. so these values are in a script tag then firstly tried to find all <script>
tags then tried to iterate over this and then there is __bbox
inside the tags which contains the values wanted to scrape.
so this is my script:
import json
import requests
import bs4
from Essentials import Static
class CmsIDs:
def GetIDs():
# cont = requests.get(""https://www.facebook.com:443/help"", headers=Static.headers) # syntax error
cont = requests.get("https://www.facebook.com:443/help", headers=Static.headers)
soup = bs4.BeautifulSoup(cont.content, "html5lib")
text = soup.find_all("script")
start = ""
txtstr = ""
for i in range(len(text)):
mystr = text[i]
# mystr = text[i]
print("this is: ", mystr.find('__bbox":'))
if text[i].get_text().find('__bbox":') != -1:
# print(i, text[i].get_text())
txtstr = text[i].get_text()
start = text[i].get_text().find('__bbox":') len('__bbox":')
print('start:', start)
count = 0
for end, char in enumerate(txtstr[start:], start):
if char == '{':
count = 1
if char == '}':
count -= 1
if count == 0:
break
print('end:', end)
# --- convert JSON string to Python structure (dict/list) ---
data = json.loads(txtstr[start:end 1])
# pp.pprint(data)
print('--- search ---')
CmsIDs.search(data)
# --- use recursion to find all 'cms_object_id', 'cmsID', 'name' ---
def search(data):
if isinstance(data, dict):
found = False
if 'cms_object_id' in data:
print('cms_object_id', data['cms_object_id'])
found = True
if 'cmsID' in data:
print('cmsID', data['cmsID'])
found = True
if 'name' in data:
print('name', data['name'])
found = True
if found:
print('---')
for val in data.values():
CmsIDs.search(val)
if isinstance(data, list):
for val in data:
CmsIDs.search(val)
if __name__ == '__main__':
CmsIDs.GetIDs()
the page contains cms_object_id
, cmsID
, name
. so wanted to scrape all these 3 values but I am getting an error:
for end, char in enumerate(txtstr[start:], start):
TypeError: slice indices must be integers or None or have an __index__ method
so how can I solve this error and reach ultimate goal?
CodePudding user response:
Note: Since I'm unfamiliar with and failed to install Essentials
, and also because ""https://www.facebook.com:443/help""
raises a syntax error (there should only be one quote on each side of the string), I changed the requests
line in my code.
cont = requests.get('https://www.facebook.com:443/help', headers={'accept': 'text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'})
TypeError: slice indices must be integers or None or have an __index__ method
You've initiated start
as a string [start = ""
] and it needs to be an integer. Unless the if text[i].get_text().find('__bbox":') != -1....
block is entered, start
remains a string.
if you just want to not get this error, you could just exit the program if start
hasn't been updated [indicating that __bbox":
wasn't found in any of the script
tags].
print('start:', start)
if start == "":
print('{__bbox":} not found')
return
count = 0
But that still leaves the problem of __bbox":
not being found; I'm not sure why, but the issue is resolved for me if I don't use the html5lib
parser - just changing to BeautifulSoup(cont.content)
resolved this issue.
# soup = bs4.BeautifulSoup(cont.content, "html5lib")
soup = bs4.BeautifulSoup(cont.content) # don't define the parser
# soup = bs4.BeautifulSoup(cont.content, "html.parser") # you could also try other parsers
Other suggestions
Your code will probably work without these, but you might want to consider these suggested improvements for error-handling:
Filter the script
Tags
If the text
ResultSet only has script
tags that contain __bbox":
, you avoid looping unnecessarily through the 100 other script
s, and you won't have to check with if....find('__bbox":')
anymore.
text = soup.find_all(lambda t: t.name == 'script' and '"__bbox"' in t.get_text())
for mystr in [s.get_text() for s in text]:
print("this is: ", mystr.find('__bbox":'))
txtstr = mystr
start = mystr.find('__bbox":') len('__bbox":')
Initiate end
You should initiate the end
variable [like end = 0
] before the for end, char ...
loop because you're using it after the loop as well.
print('end:', end)
data = json.loads(txtstr[start:end 1])
If txtstr[start:]
is empty somehow, these lines will raise error/s since end
would not be defined yet.
Use a JavaScript Parser
This will make the previous suggestions unnecessary, but as it is json.loads
will raise an error if txtstr[start:end 1]
is empty somehow, or if it contains any unpaired [and likely escaped] }
or{
. So, it might be more reliable to use a parser rather than just trying to walk through the string.
I have this function that uses slimit
to find values from strings containing JavaScript code. (It's far from perfect, but it seems to for this script, at least.) GetIDs()
could be re-written as below.
# import json, requests, bs4, slimit
# from slimit.visitors import nodevisitor
# def findObj_inJS... ## PASTE FROM https://pastebin.com/UVcLniSG
# class CmsIDs:
def GetIDs():
# cont=requests.get('https://www.facebook.com:443/help',headers=Static.headers)
cont = requests.get('https://www.facebook.com:443/help', headers={
'accept': ';'.join(
[ 'text/html,application/xhtml xml,application/xml',
'q=0.9,image/avif,image/webp,image/apng,*/*',
'q=0.8,application/signed-exchange',
'v=b3', 'q=0.9' ])})
## in case of request errors ##
try: cont.raise_for_status()
except Exception as e:
print('failed to fetch page HTML -', type(e), e)
return
print('fetched', cont.url, 'with', cont.status_code, cont.reason)
soup = bs4.BeautifulSoup(cont.content)
scrCond = lambda t: t.name == 'script' and '"__bbox"' in t.get_text()
jScripts = [s.get_text() for s in soup.find_all(scrCond)]
print(f'Found {len(jScripts)} script tags containing {{"__bbox"}}')
data = [findObj_inJS(s,'"__bbox"') for s in jScripts]
print('--- search ---')
CmsIDs.search(data)
# def search(data)....
Return the Data
This isn't for error-handling, but if you return the data printed by CmsIDs.search
you could save it for further use.
def search(data):
rList, dKeys = [], ['cms_object_id', 'cmsID', 'name']
if isinstance(data, dict):
dObj = {k: data[k] for k in dKeys if k in data}
rList = [dObj] if dObj else []
for k, v in dObj.items(): print(k, v)
if dObj: print('---')
for val in data.values(): rList = CmsIDs.search(val)
if isinstance(data, list):
for val in data: rList = CmsIDs.search(val)
return rList
The printed result will be the same as before, but if you change the last line of GetIDs
to
return CmsIDs.search(data)
and then define a variable cmsList = CmsIDs.GetIDs()
then cmsList
will be a list of dctionaries, which you could then [for example] save to csv with pandas
and view as a table on a spreadsheet.
# import pandas
pandas.DataFrame(cmsList).to_csv('CmsIDs_GetIDs.csv', index=False)
or print the markdown for the table [of the results I got] below
print(pandas.DataFrame(cmsList, dtype=str).fillna('').to_markdown())
[index] | cms_object_id | name | cmsID |
---|---|---|---|
0 | Використання Facebook | ||
1 | 570785306433644 | Створення облікового запису | |
2 | 396528481579093 | Your Profile | |
3 | Додати й редагувати інформацію у своєму профілі | 1017657581651994 | |
4 | Ваші основна світлина й обкладинка | 1217373834962306 | |
5 | Поширення дописів у своєму профілі та керування ними | 1640261589632787 | |
6 | Усунення проблем | 191128814621591 | |
7 | 1540345696275090 | Додавання в друзі | |
8 | Додавання друзів | 246750422356731 | |
9 | Люди, яких ви можете знати | 336320879782850 | |
10 | Control Who Can Friend and Follow You | 273948399619967 | |
11 | Upload Your Contacts to Facebook | 1041444532591371 | |
12 | Видалення з друзів чи блокування користувача | 1000976436606344 | |
13 | 312959615934334 | Facebook Dating | |
14 | 753701661398957 | Ваша головна сторінка | |
15 | How Feed Works | 1155510281178725 | |
16 | Control What You See in Feed | 964154640320617 | |
17 | Like and React to Posts | 1624177224568554 | |
18 | Пошук | 821153694683665 | |
19 | Translate Feed | 1195058957201487 | |
20 | Memories | 1056848067697293 | |
21 | 1071984682876123 | Повідомлення | |
22 | Надсилання повідомлень | 487151698161671 | |
23 | Переглянути повідомлення й керувати ними | 1117039378334299 | |
24 | Поскаржитися на повідомлення | 968185709965912 | |
25 | Відеовиклики | 287631408243374 | |
26 | Fix a Problem | 1024559617598844 | |
27 | 753046815962474 | Reels | |
28 | Watching Reels | 475378724739085 | |
29 | Creating Reels | 867690387846185 | |
30 | Managing Your Reels | 590925116168623 | |
31 | 862926927385914 | Розповіді | |
32 | Як створити розповідь і поширити її | 126560554619115 | |
33 | View and Reply to Stories | 349797465699432 | |
34 | Page Stories | 425367811379971 | |
35 | 1069521513115444 | Світлини й відео | |
36 | Світлини | 1703757313215897 | |
37 | Відео | 1738143323068602 | |
38 | Going Live | 931327837299966 | |
39 | Albums | 490693151131920 | |
40 | Додавання позначок | 267689476916031 | |
41 | Усунення проблеми | 507253956146325 | |
42 | 1041553655923544 | Відео у Watch | |
43 | Перегляд шоу та відео | 401287967326510 | |
44 | Fix a Problem | 270093216665260 | |
45 | 2402655169966967 | Gaming | |
46 | Gaming on Facebook | 385894640264219 | |
47 | Платежі в іграх | 248471068848455 | |
48 | 282489752085908 | Сторінки | |
49 | Interact with Pages | 1771297453117418 | |
50 | Створити сторінку й керувати нею | 135275340210354 | |
51 | Імена й імена користувачів | 1644118259243888 | |
52 | Керування налаштуваннями сторінки | 1206330326045914 | |
53 | Customize a Page | 1602483780062090 | |
54 | Publishing | 1533298140275888 | |
55 | Messaging | 994476827272050 | |
56 | Insights | 794890670645072 | |
57 | Banning and Moderation | 248844142141117 | |
58 | Усунути проблему | 1020132651404616 | |
59 | 1629740080681586 | Групи | |
60 | Join and Choose Your Settings | 1210322209008185 | |
61 | Post, Participate and Privacy | 530628541788770 | |
62 | Create, Engage and Manage Settings | 408334464841405 | |
63 | Керування групою для адміністраторів | 1686671141596230 | |
64 | Community Chats | 3397387057158160 | |
65 | Pages in Groups | 1769476376397128 | |
66 | Fix a Problem | 1075368719167893 | |
67 | 1076296042409786 | Події | |
68 | Create and Manage an Event | 572885262883136 | |
69 | View and Respond to Events | 1571121606521970 | |
70 | Facebook Classes | 804063877226739 | |
71 | 833144153745643 | Fundraisers and Donations | |
72 | Creating a Fundraiser | 356680401435429 | |
73 | Пожертва в рамках збору коштів | 1409509059114623 | |
74 | Особисті збори коштів | 332739730519432 | |
75 | For Nonprofits | 1640008462980459 | |
76 | Fix a Problem | 2725517974129416 | |
77 | 1434403039959381 | Meta Pay | |
78 | Платежі в іграх | 248471068848455 | |
79 | Payments in Messages | 863171203733904 | |
80 | Пожертва в рамках збору коштів | 1409509059114623 | |
81 | Квитки на заходи | 1769557403280350 | |
82 | Monetization and Payouts | 1737820969853848 | |
83 | 1713241952104830 | Marketplace | |
84 | Як працює Marketplace | 1889067784738765 | |
85 | Buying on Marketplace | 272975853291364 | |
86 | Продаж на Marketplace | 153832041692242 | |
87 | Sell with Shipping on Marketplace | 773379109714742 | |
88 | Using Checkout on Facebook | 1411280809160810 | |
89 | Групи з купівлі й продажу | 319768015124786 | |
90 | Get Help with Marketplace | 1127970530677256 | |
91 | 1642635852727373 | Додатки | |
92 | Manage Your Apps | 942196655898243 | |
93 | Видимість і конфіденційність додатка | 1727608884153160 | |
94 | 866249956813928 | Додатки Facebook для мобільних пристроїв | |
95 | Додаток для Android | 1639918076332350 | |
96 | iPhone and iPad Apps | 1158027224227668 | |
97 | Facebook Lite App | 795302980569545 | |
98 | 273947702950567 | Спеціальні можливості | |
99 | Керування обліковим записом | ||
100 | 1573156092981768 | Вхід і пароль | |
101 | Вхід в обліковий запис | 1058033620955509 | |
102 | Змінення пароля | 248976822124608 | |
103 | Виправлення проблеми із входом | 283100488694834 | |
104 | Завантаження посвідчення особи | 582999911881572 | |
105 | 239070709801747 | Налаштування облікового запису | |
106 | Як змінити налаштування облікового запису | 1221288724572426 | |
107 | Ваше ім’я користувача | 1740158369563165 | |
108 | Спадкоємці | 991335594313139 | |
109 | 1090831264320592 | Імена у Facebook | |
110 | 1036755649750898 | Сповіщення | |
111 | Push, Email and Text Notifications | 530847210446227 | |
112 | Виберіть, про що отримувати сповіщення | 269880466696699 | |
113 | Усунення проблем | 1719980288275077 | |
114 | 109378269482053 | Налаштування реклами | |
115 | Як працює реклама у Facebook | 516147308587266 | |
116 | Контроль реклами, яку ви бачите | 1075880512458213 | |
117 | Ваша інформація та реклама у Facebook | 610457675797481 | |
118 | 1701730696756992 | Доступ до вашої інформації та її завантаження | |
119 | 250563911970368 | Деактивація або видалення облікового запису | |
120 | Конфіденційність і безпека | ||
121 | 238318146535333 | Ваша конфіденційність | |
122 | Керуйте тим, хто може переглядати контент, який ви поширюєте у Facebook | 1297502253597210 | |
123 | Керування своїми дописами | 504765303045427 | |
124 | Control Who Can Find You | 1718866941707011 | |
125 | 592679377575472 | Безпека | |
126 | Джерела щодо боротьби з жорстоким поводженням | 726709730764837 | |
127 | Ресурси з допомоги для протидії самогубству та самоушкодженню | 1553737468262661 | |
128 | Crisis Response | 141874516227713 | |
129 | Ресурси з правил безпеки для допомоги батькам | 1079477105456277 | |
130 | Інформація для правоохоронних органів | 764592980307837 | |
131 | 235353253505947 | Захист облікового запису | |
132 | Функції безпеки та поради з її забезпечення | 285695718429403 | |
133 | Сповіщення про вхід і двоетапна перевірка | 909243165853369 | |
134 | Уникайте спаму та шахрайства | 1584206335211143 | |
135 | 236079651241697 | Безпека під час здійснення покупок | |
136 | Розпізнавання шахрайства | 1086141928978559 | |
137 | Уникнення шахрайства | 2374002556073992 | |
138 | Купівля на Marketplace | 721562085854101 | |
139 | Поради щодо безпечної купівлі | 123884166448529 | |
140 | Купуйте впевнено | 1599248863596914 | |
141 | Політики та скарги | ||
142 | 1753719584844061 | Скарга на порушення | |
143 | Як поскаржитися на щось? | 1380418588640631 | |
144 | Don't Have an Account? | 1723400564614772 | |
145 | 1126628984024935 | Як повідомити про проблему у Facebook | |
146 | 186614050293763 | Being Your Authentic Self on Facebook | |
147 | 1561472897490627 | Повідомлення про порушення конфіденційності | |
148 | 1216349518398524 | Зламані та фальшиві облікові записи | |
149 | 275013292838654 | Керування обліковим записом померлої людини | |
150 | About Memorialized Accounts | 1017717331640041 | |
151 | Request to Memorialize or Remove an Account | 1111566045566400 | |
152 | 399224883474207 | Інтелектуальна власність | |
153 | Авторське право | 1020633957973118 | |
154 | Торговельна марка | 507663689427413 | |
155 | 1735443093393986 | Про наші політики |