NLPGenius commited on
Commit
05fd838
·
verified ·
1 Parent(s): 57eafed

Update propakistani.py

Browse files
Files changed (1) hide show
  1. propakistani.py +210 -154
propakistani.py CHANGED
@@ -1,154 +1,210 @@
1
- import time
2
- import random
3
- import csv
4
- import cloudscraper
5
- from bs4 import BeautifulSoup
6
-
7
- # Base URL
8
- BASE_URL = "https://propakistani.pk/"
9
-
10
- # User-Agent List
11
- USER_AGENTS = [
12
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
13
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
14
- "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/537.36 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/537.36",
15
- "Mozilla/5.0 (Linux; Android 14; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
16
- ]
17
-
18
- def fetch_articles():
19
- """Fetches articles from ProPakistani homepage"""
20
- scraper = cloudscraper.create_scraper()
21
- headers = {"User-Agent": random.choice(USER_AGENTS)}
22
- response = scraper.get(BASE_URL, headers=headers, allow_redirects=True)
23
-
24
- if response.status_code != 200:
25
- print(f"Failed to fetch page. Status: {response.status_code}")
26
- return []
27
-
28
- soup = BeautifulSoup(response.text, "html.parser")
29
- articles = []
30
- processed_urls = set()
31
- article_count = 0
32
-
33
- for item in soup.select('a[href^="https://propakistani.pk/"]'):
34
- if article_count >= 10:
35
- break
36
-
37
- article_url = item["href"].split('?')[0] # Remove URL parameters
38
- if article_url in processed_urls:
39
- continue
40
-
41
- title, date, author, article_text = fetch_article_text(article_url, scraper)
42
-
43
- if all([title != "No title", date != "No date",
44
- author != "No author", article_text != "No content"]):
45
- articles.append({
46
- "URL": article_url,
47
- "Date": date,
48
- "Title": title,
49
- "Author": author,
50
- "Category": "Latest News",
51
- "Article_text": article_text
52
- })
53
- processed_urls.add(article_url)
54
- article_count += 1
55
- time.sleep(random.uniform(2, 5))
56
-
57
- return articles
58
-
59
- def fetch_article_text(article_url, scraper):
60
- """Extracts and cleans article content with ad removal"""
61
- headers = {"User-Agent": random.choice(USER_AGENTS)}
62
- try:
63
- response = scraper.get(article_url, headers=headers, timeout=30)
64
- response.raise_for_status()
65
- except Exception as e:
66
- print(f"Error fetching article: {str(e)}")
67
- return "No title", "No date", "No author", "No content"
68
-
69
- soup = BeautifulSoup(response.text, "html.parser")
70
-
71
- # Extract metadata
72
- title = soup.select_one('.entry-title').get_text(strip=True) if soup.select_one('.entry-title') else "No title"
73
- date = soup.select_one('.entry-meta span.d-block.d-md-inline').get_text(strip=True) if soup.select_one('.entry-meta span.d-block.d-md-inline') else "No date"
74
- author = soup.select_one('.author.vcard a').get_text(strip=True) if soup.select_one('.author.vcard a') else "No author"
75
-
76
-
77
- print(f"Scraped article: {title}")
78
- # Extract and clean main content
79
- content_div = soup.select_one('.entry-content .the-post-content')
80
- if not content_div:
81
- return title, date, author, "No content"
82
-
83
- # Remove advertisement elements
84
- ad_selectors = [
85
- '.inter-linking-text', # Target specific ad container
86
- '.p-alsoread',
87
- '.code-block',
88
- '.donations-wrapper',
89
- '.av-ads',
90
- '.social-share',
91
- 'script',
92
- 'style',
93
- '[data-google-query-id]',
94
- '[data-rocket-status]',
95
- '.av-adLabel'
96
- ]
97
-
98
- for selector in ad_selectors:
99
- for element in content_div.select(selector):
100
- element.decompose()
101
-
102
- # Remove empty paragraphs and clean text
103
- clean_paragraphs = []
104
- for p in content_div.find_all(['p', 'h2', 'h3']):
105
- text = p.get_text(strip=True)
106
- if text and len(text) > 30: # Filter short text fragments
107
- clean_paragraphs.append(text)
108
-
109
- article_text = '\n'.join(clean_paragraphs)
110
-
111
- # Remove remaining ad phrases
112
- ad_phrases = [
113
- "If you can, please support us",
114
- "Follow ProPakistani on Google News",
115
- "Support independent journalism",
116
- "For the latest Business news"
117
- ]
118
-
119
- for phrase in ad_phrases:
120
- if phrase in article_text:
121
- article_text = article_text.split(phrase)[0].strip()
122
- break
123
-
124
- return title, date, author, article_text.strip()
125
-
126
- def save_to_csv(articles, filename="ProPakistani_News.csv"):
127
- """Saves articles to CSV"""
128
- if not articles:
129
- print("No articles to save")
130
- return
131
-
132
- try:
133
- with open(filename, "w", newline="", encoding="utf-8") as csvfile:
134
- writer = csv.DictWriter(csvfile, fieldnames=articles[0].keys())
135
- writer.writeheader()
136
- writer.writerows(articles)
137
- print(f"Saved {len(articles)} articles to {filename}")
138
- except Exception as e:
139
- print(f"Error saving CSV: {str(e)}")
140
-
141
- def main():
142
- """Main function"""
143
- print("\nScraping ProPakistani...")
144
- start_time = time.time()
145
-
146
- articles = fetch_articles()
147
-
148
- if articles:
149
- return articles
150
- else:
151
- print("No articles found")
152
-
153
- if __name__ == "__main__":
154
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import random
3
+ import csv
4
+ import cloudscraper
5
+ from bs4 import BeautifulSoup
6
+ import logging
7
+
8
+ # Configure logging
9
+ logging.basicConfig(
10
+ level=logging.INFO,
11
+ format='%(asctime)s - %(levelname)s - %(message)s'
12
+ )
13
+
14
+ # Base URL
15
+ BASE_URL = "https://propakistani.pk/"
16
+
17
+ # User-Agent List
18
+ USER_AGENTS = [
19
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
20
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
21
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/537.36 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/537.36",
22
+ "Mozilla/5.0 (Linux; Android 14; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
23
+ ]
24
+
25
+ def fetch_articles():
26
+ """Fetches articles from ProPakistani homepage."""
27
+ scraper = cloudscraper.create_scraper()
28
+ headers = {"User-Agent": random.choice(USER_AGENTS)}
29
+
30
+ try:
31
+ response = scraper.get(BASE_URL, headers=headers, allow_redirects=True, timeout=30)
32
+ except Exception as e:
33
+ logging.error(f"Error fetching the homepage: {e}", exc_info=True)
34
+ return []
35
+
36
+ if response.status_code != 200:
37
+ logging.error(f"Failed to fetch page. Status code: {response.status_code}")
38
+ return []
39
+
40
+ soup = BeautifulSoup(response.text, "html.parser")
41
+ articles = []
42
+ processed_urls = set()
43
+ article_count = 0
44
+
45
+ # Look for links that match the article URL pattern
46
+ for item in soup.select('a[href^="https://propakistani.pk/"]'):
47
+ if article_count >= 10:
48
+ break
49
+
50
+ try:
51
+ article_url = item["href"].split('?')[0] # Remove URL parameters
52
+ except KeyError as e:
53
+ logging.warning(f"Missing href in an element: {e}")
54
+ continue
55
+
56
+ if article_url in processed_urls:
57
+ continue
58
+
59
+ title, date, author, article_text = fetch_article_text(article_url, scraper)
60
+
61
+ if all([title != "No title", date != "No date",
62
+ author != "No author", article_text != "No content"]):
63
+ articles.append({
64
+ "URL": article_url,
65
+ "Date": date,
66
+ "Title": title,
67
+ "Author": author,
68
+ "Category": "Latest News",
69
+ "Article_text": article_text
70
+ })
71
+ processed_urls.add(article_url)
72
+ article_count += 1
73
+ # Wait a random interval to be polite to the server
74
+ time.sleep(random.uniform(2, 5))
75
+
76
+ return articles
77
+
78
+ def fetch_article_text(article_url, scraper):
79
+ """Extracts and cleans article content with ad removal."""
80
+ headers = {"User-Agent": random.choice(USER_AGENTS)}
81
+ try:
82
+ response = scraper.get(article_url, headers=headers, timeout=30)
83
+ response.raise_for_status()
84
+ except Exception as e:
85
+ logging.error(f"Error fetching article {article_url}: {e}", exc_info=True)
86
+ return "No title", "No date", "No author", "No content"
87
+
88
+ soup = BeautifulSoup(response.text, "html.parser")
89
+
90
+ # Extract metadata with error handling
91
+ try:
92
+ title_elem = soup.select_one('.entry-title')
93
+ title = title_elem.get_text(strip=True) if title_elem else "No title"
94
+ except Exception as e:
95
+ logging.error(f"Error extracting title from {article_url}: {e}", exc_info=True)
96
+ title = "No title"
97
+
98
+ try:
99
+ date_elem = soup.select_one('.entry-meta span.d-block.d-md-inline')
100
+ date = date_elem.get_text(strip=True) if date_elem else "No date"
101
+ except Exception as e:
102
+ logging.error(f"Error extracting date from {article_url}: {e}", exc_info=True)
103
+ date = "No date"
104
+
105
+ try:
106
+ author_elem = soup.select_one('.author.vcard a')
107
+ author = author_elem.get_text(strip=True) if author_elem else "No author"
108
+ except Exception as e:
109
+ logging.error(f"Error extracting author from {article_url}: {e}", exc_info=True)
110
+ author = "No author"
111
+
112
+ logging.info(f"Scraped article: {title}")
113
+
114
+ # Extract and clean main content
115
+ content_div = soup.select_one('.entry-content .the-post-content')
116
+ if not content_div:
117
+ logging.warning(f"Article content not found in {article_url}")
118
+ return title, date, author, "No content"
119
+
120
+ # Remove advertisement elements
121
+ ad_selectors = [
122
+ '.inter-linking-text',
123
+ '.p-alsoread',
124
+ '.code-block',
125
+ '.donations-wrapper',
126
+ '.av-ads',
127
+ '.social-share',
128
+ 'script',
129
+ 'style',
130
+ '[data-google-query-id]',
131
+ '[data-rocket-status]',
132
+ '.av-adLabel'
133
+ ]
134
+
135
+ for selector in ad_selectors:
136
+ for element in content_div.select(selector):
137
+ try:
138
+ element.decompose()
139
+ except Exception as e:
140
+ logging.error(f"Error removing element {selector} in {article_url}: {e}", exc_info=True)
141
+
142
+ # Remove empty paragraphs and clean text
143
+ clean_paragraphs = []
144
+ for p in content_div.find_all(['p', 'h2', 'h3']):
145
+ try:
146
+ text = p.get_text(strip=True)
147
+ if text and len(text) > 30: # Filter short text fragments
148
+ clean_paragraphs.append(text)
149
+ except Exception as e:
150
+ logging.error(f"Error processing text in {article_url}: {e}", exc_info=True)
151
+
152
+ article_text = '\n'.join(clean_paragraphs)
153
+
154
+ # Remove any remaining ad phrases
155
+ ad_phrases = [
156
+ "If you can, please support us",
157
+ "Follow ProPakistani on Google News",
158
+ "Support independent journalism",
159
+ "For the latest Business news"
160
+ ]
161
+
162
+ for phrase in ad_phrases:
163
+ if phrase in article_text:
164
+ article_text = article_text.split(phrase)[0].strip()
165
+ break
166
+
167
+ return title, date, author, article_text.strip()
168
+
169
+ def save_to_csv(articles, filename="ProPakistani_News.csv"):
170
+ """Saves articles to a CSV file."""
171
+ if not articles:
172
+ logging.info("No articles to save.")
173
+ return
174
+
175
+ try:
176
+ with open(filename, "w", newline="", encoding="utf-8") as csvfile:
177
+ writer = csv.DictWriter(csvfile, fieldnames=articles[0].keys())
178
+ writer.writeheader()
179
+ writer.writerows(articles)
180
+ logging.info(f"Saved {len(articles)} articles to {filename}")
181
+ except Exception as e:
182
+ logging.error(f"Error saving CSV: {e}", exc_info=True)
183
+
184
+ def main():
185
+ """Main function to coordinate scraping and saving."""
186
+ logging.info("Starting to scrape ProPakistani...")
187
+ start_time = time.time()
188
+
189
+ try:
190
+ articles = fetch_articles()
191
+ except Exception as e:
192
+ logging.error(f"Unexpected error during fetching articles: {e}", exc_info=True)
193
+ articles = []
194
+
195
+ if articles:
196
+ try:
197
+ save_to_csv(articles)
198
+ except Exception as e:
199
+ logging.error(f"Unexpected error during saving articles: {e}", exc_info=True)
200
+ else:
201
+ logging.info("No articles found.")
202
+
203
+ elapsed = time.time() - start_time
204
+ logging.info(f"Total time taken: {elapsed:.2f} seconds")
205
+
206
+ if __name__ == "__main__":
207
+ try:
208
+ main()
209
+ except Exception as e:
210
+ logging.critical(f"Fatal error in main: {e}", exc_info=True)